How to get a validator to work in a frame

Below is the complete code (yes, all of it this time!). I'm not sure
if the validator is being called or not. According to wxPython in
Action, since it's a frame instead of a dialog, I need to call the
Validate() method explicitly. I think I'm doing that right, but the
program just throws the error on:

self.time = int(self.input.GetValue())

(if I leave the input box blank) as if it just skipped over any
validation stuff. I'm sure there's one little thing I'm not hooking up
right.

Thanks,
John

···

-------------------------

from __future__ import division
import wx

class NumbersValidator(wx.PyValidator):

    def __init__(self):
        wx.PyValidator.__init__(self)

    def Clone(self):
        return NumbersValidator()

    def Validate(self, parent):
        text_ctrl = self.GetWindow()
        text = text_ctrl.GetValue()

        if len(text) == 0:
            wx.MessageBox('Enter a valid time.', 'Invalid time entered',
                          wx.OK | wx.ICON_ERROR)
            return False
        else:
            return True

    def TransferToWindow(self):
        return True

    def TransferFromWindow(self):
        return True

class MyTimer(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, 'Timer',
                          style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER
                          ^ wx.MAXIMIZE_BOX)
        panel = wx.Panel(self)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        inputSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.progress = wx.Gauge(panel, wx.ID_ANY, 100, size=(300, 20))
        self.status = wx.StaticText(panel, wx.ID_ANY, 'Enter a time.')
        prompt = wx.StaticText(panel, wx.ID_ANY, 'Time to wait:')
        self.input = wx.TextCtrl(panel, wx.ID_ANY, size=(20, 20),
                                 validator=NumbersValidator())
        self.start = wx.Button(panel, wx.ID_ANY, 'Start')
        self.reset = wx.Button(panel, wx.ID_ANY, 'Reset')
        self.reset.Disable()
        self.sound = wx.Sound(r'C:\Windows\Media\notify.wav')
        self.timer = wx.Timer(self)

        mainSizer.Add(self.progress, flag=wx.ALIGN_CENTER | wx.ALL ^ wx.BOTTOM,
                      border=10)
        mainSizer.Add(self.status, flag=wx.ALIGN_CENTER | wx.ALL, border=10)
        mainSizer.Add(inputSizer, flag=wx.ALIGN_CENTER | wx.BOTTOM, border=10)
        inputSizer.Add(prompt, flag=wx.ALIGN_CENTER)
        inputSizer.Add(self.input, flag=wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT,
                       border=5)
        inputSizer.Add(self.start, flag=wx.ALIGN_CENTER)
        inputSizer.Add(self.reset, flag=wx.ALIGN_CENTER)

        self.Bind(wx.EVT_TEXT_ENTER, self.OnStart, self.input)
        self.Bind(wx.EVT_BUTTON, self.OnStart, self.start)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.Bind(wx.EVT_BUTTON, self.OnReset, self.reset)

        panel.SetSizer(mainSizer)
        mainSizer.Fit(self)

    def OnStart(self, event):
        self.input.Validate()
        self.time = int(self.input.GetValue())
        self.minutes_passed = 1
        self.minutes_remaining = self.time - 1
        self.start.Disable()
        self.input.Disable()
        self.reset.Enable()
        self.status.SetLabel('%s minute(s) remaining.' % self.time)
        self.timer.Start(1000)

    def OnReset(self, event):
        if self.timer.IsRunning():
            self.timer.Stop()
        self.input.Clear()
        self.input.Enable()
        self.start.Enable()
        self.reset.Disable()
        self.status.SetLabel('Enter a new time.')
        self.progress.SetValue(0)
        self.minutes_passed = 1

    def OnTimer(self, event):
        if self.minutes_remaining != 0:
            self.progress.SetValue(self.minutes_passed * 100 / self.time)
            self.status.SetLabel('%s minute(s) remaining.' %
self.minutes_remaining)
            self.minutes_passed += 1
            self.minutes_remaining -= 1
        else:
            self.timer.Stop()
            self.progress.SetValue(self.minutes_passed * 100 / self.time)
            self.status.SetLabel('%s minute(s) have elapsed.' % self.time)
            wx.Sound.Play(self.sound)

class MyApp(wx.App):

    def OnInit(self):
        frame = MyTimer()
        self.SetTopWindow(frame)
        frame.Show()
        return True

if __name__ == '__main__':
    app = MyApp(False)
    app.MainLoop()

Below is the complete code (yes, all of it this time!). I'm not sure
if the validator is being called or not. According to wxPython in
Action, since it's a frame instead of a dialog, I need to call the
Validate() method explicitly. I think I'm doing that right, but the
program just throws the error on:

self.time = int(self.input.GetValue())

(if I leave the input box blank) as if it just skipped over any
validation stuff. I'm sure there's one little thing I'm not hooking up
right.

I think it has nothing to do with wxPython. Probably you are trying to
convert an empty string into an integer. You should first get the
value as a string and test if it is not empty before converting to an
integer.

This what you try to do:

int('')

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: invalid literal for int():

Stani

···

On 7/28/06, John Salerno <johnjsal@gmail.com> wrote:
--

http://pythonide.stani.be/screenshots
http://pythonide.stani.be/manual/html/manual.html

SPE Stani's Python Editor wrote:

You should first get the
value as a string and test if it is not empty before converting to an
integer.

or wrap it in a try: block --

try:
    self.time = int(self.input.GetValue())
    <do what you need to do>
except ValueError:
     <do something else -- I usually do nothing>

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov