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) 41 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()