How to Properly Use Wx. Calllater in Wx. Python
I Want to Loop and Call a Function Every 1000 Milliseconds with Wx. Calllater. I Implemented This (See Below), but It Does Not Factor in the Delay - It Seems...
I want to loop and call a function every 1000 milliseconds with wx.CallLater. I implemented this (see below), but it does not factor in the delay - it seems to execute automatically. How can I get this to wait 1000 milliseconds between function calls?
This function is within a class. In my main module, I instantiate an object of this class and call the task_loop function. I intend to keep the loop going until will_break is set to True, and task_loop returns the work_session_agenda in the main module. Thank you for your help!
def task_loop(self, duration, window, task, work_session_agenda, start, completed):
will_break = False
will_continue = False
duration -= datetime.timedelta(seconds=1)
More code in here - which, depending on conditionals, sets the values of will_break and will_continue
if will_break:
print('BREAKING')
return work_session_agenda
else:
print('GOT HERE')
timer = wx.CallLater(1000, self.task_loop, duration, window, task, work_session_agenda, start, completed)
1 Answer
Below you can find an example with wx.CallLater and with wx.Timer as suggested in the comments. Notice that in both cases the GUI remains responsive during the waiting time.
With wx.Timer
import wx
import time
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(None, title="With wx.Timer", size=(500,500))
#### Variables
self.will_continue = True
self.i = 0
self.total = 5
self.mili = 1000
#### Widgets
# Parent panel
self.panel = wx.Panel(self)
# Button
self.button = wx.Button(self.panel, label="Start", pos=(50, 50))
self.button2 = wx.Button(self.panel, label="Button", pos=(50 ,100))
#### Timer Notice that wx.Timer is own by the frame itself
self.timer = wx.Timer(self)
#### Bind
self.button.Bind(wx.EVT_BUTTON, self.OnStart)
self.Bind(wx.EVT_TIMER, self.OnCheck, self.timer)
def OnStart(self, event):
## OnStart, disable the button and change its label and start the timer.
## Notice with Button that the GUI remain responsive
## while the timer runs
if self.will_continue:
print(self.i)
print(time.ctime())
self.button.SetLabel("Running")
self.button.Disable()
self.timer.Start(self.mili)
## When finish waiting reset everything so the start button can run
## again and stop the timer
else:
self.timer.Stop()
self.button.SetLabel("Start")
self.button.Enable()
self.will_continue = True
self.i = 0
def OnCheck(self, event):
self.i += 1
if self.i > self.total:
self.will_continue = False
else:
pass
self.OnStart(event)
# Run the program
if __name__ == "__main__":
app = wx.App()
frame = MyFrame()
frame.Show()
app.MainLoop()
With wx.CallLater
import wx
import time
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(None, title="With wx.CallAfter", size=(500,500))
#### Variables
self.will_continue = True
self.i = 0
self.total = 5
self.mili = 1000
#### Widgets
# Parent panel
self.panel = wx.Panel(self)
# Button
self.button = wx.Button(self.panel, label="Start", pos=(50, 50))
self.button2 = wx.Button(self.panel, label="Button", pos=(50 ,100))
#### Bind
self.button.Bind(wx.EVT_BUTTON, self.OnStart)
def OnStart(self, event):
## OnStart, disable the button and change its label and make the
## wx.CallLater call. Notice with Button that the GUI remain responsive
## while wx.CallLater waits
if self.will_continue:
print(self.i)
print(time.ctime())
self.button.SetLabel("Running")
self.button.Disable()
wx.CallLater(self.mili, self.OnCheck, event)
## When finish waiting reset everything so the start button can run
## again
else:
self.button.SetLabel("Start")
self.button.Enable()
self.will_continue = True
self.i = 0
def OnCheck(self, event):
self.i += 1
if self.i > self.total:
self.will_continue = False
else:
pass
self.OnStart(event)
# Run the program
if __name__ == "__main__":
app = wx.App()
frame = MyFrame()
frame.Show()
app.MainLoop()