wxpython: Timer object not working, or just me?

J

John Salerno

I'd be curious to know if this works any differently on other
computers/platforms or while other things are happening in the
background. I can't tell if it's the Timer object that isn't keep
accurate time (although a test with time.time() seems to show that it
is), or if I'm just messing up my algorithm to fill the progress bar. If
I put in 10 seconds, the progress bar will be fully filled at the end,
but if you put 30, it doesn't. As the number gets higher, the less the
bar gets filled when it's done running. (52 seconds only fills half the
bar at the end!)

Hopefully someone can look at my logic (mostly in the OnTimer method)
and see right away how I'm screwing this up.

Thanks.

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

import wx


class MyTimer(wx.Frame):

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

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

self.minutesPassed = 1
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, '30', size=(20, 20))
self.start = wx.Button(panel, wx.ID_ANY, 'Start')
self.reset = wx.Button(panel, wx.ID_ANY, 'Reset')
self.reset.Disable()
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.time = int(self.input.GetValue())
self.countdown = self.time - 1
self.start.Disable()
self.reset.Enable()
self.input.Disable()
self.status.SetLabel('%s minutes remaining.' % self.time)
self.timer.Start(1000)

def OnReset(self, event):
self.input.Clear()
self.status.SetLabel('Enter a new time.')
self.progress.SetValue(0)
self.input.Enable()
self.minutesPassed = 1

def OnTimer(self, event):
if self.countdown != 0:
#print self.minutesPassed, self.countdown
self.progress.SetValue(self.minutesPassed * (100 / self.time))
self.status.SetLabel('%s minutes remaining.' % self.countdown)
self.minutesPassed += 1
self.countdown -= 1
else:
self.progress.SetValue(self.minutesPassed * (100 / self.time))
self.status.SetLabel('%s minutes have elapsed.' % self.time)


class MyApp(wx.App):

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


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

Steve Holden

John said:
I'd be curious to know if this works any differently on other
computers/platforms or while other things are happening in the
background. I can't tell if it's the Timer object that isn't keep
accurate time (although a test with time.time() seems to show that it
is), or if I'm just messing up my algorithm to fill the progress bar. If
I put in 10 seconds, the progress bar will be fully filled at the end,
but if you put 30, it doesn't. As the number gets higher, the less the
bar gets filled when it's done running. (52 seconds only fills half the
bar at the end!)

Hopefully someone can look at my logic (mostly in the OnTimer method)
and see right away how I'm screwing this up.

Thanks.

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

import wx


class MyTimer(wx.Frame):

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

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

self.minutesPassed = 1
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, '30', size=(20, 20))
self.start = wx.Button(panel, wx.ID_ANY, 'Start')
self.reset = wx.Button(panel, wx.ID_ANY, 'Reset')
self.reset.Disable()
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.time = int(self.input.GetValue())
self.countdown = self.time - 1
self.start.Disable()
self.reset.Enable()
self.input.Disable()
self.status.SetLabel('%s minutes remaining.' % self.time)
self.timer.Start(1000)

def OnReset(self, event):
self.input.Clear()
self.status.SetLabel('Enter a new time.')
self.progress.SetValue(0)
self.input.Enable()
self.minutesPassed = 1

def OnTimer(self, event):
if self.countdown != 0:
#print self.minutesPassed, self.countdown
self.progress.SetValue(self.minutesPassed * (100 / self.time))
self.status.SetLabel('%s minutes remaining.' % self.countdown)
self.minutesPassed += 1
self.countdown -= 1
else:
self.progress.SetValue(self.minutesPassed * (100 / self.time))
self.status.SetLabel('%s minutes have elapsed.' % self.time)


class MyApp(wx.App):

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


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

Integer arithmetic. Try changing the "100" to "100.0" and you'll see it
works flawlessly.

regards
Steve
 
J

John Salerno

Steve said:
Integer arithmetic. Try changing the "100" to "100.0" and you'll see it
works flawlessly.

oh my god, i don't deserve to use python!

but thanks so much! :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top