如何在wx.Python中正确使用wx.CallLater

时间:2019-05-28 01:00:06

标签: python loops user-interface wxpython

我想使用wx.CallLater每1000毫秒循环并调用一个函数。我实现了这一点(请参阅下文),但是它没有考虑延迟-它似乎是自动执行的。我如何才能在函数调用之间等待1000毫秒?

此函数在一个类中。在我的主模块中,我实例化了此类的对象并调用task_loop函数。我打算一直循环下去,直到will_break设置为True,而task_loop在主模块中返回work_session_agenda。谢谢您的帮助!

def task_loop(self, duration, window, task, work_session_agenda, start, completed):

    will_break = False
    will_continue = False

    duration -= datetime.timedelta(seconds=1)

此处有更多代码-根据条件,这些代码将设置will_break和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)

2 个答案:

答案 0 :(得分:0)

在下面您可以找到示例,其中包含wx.CallLater和注释中建议的wx.Timer。请注意,在两种情况下,GUI在等待时间内都保持响应状态。

使用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()

使用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()

答案 1 :(得分:0)

简单的计时器示例

import wx
class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, -1, title,size=(350, 225))
        panel = wx.Panel(self)
        self.Text = wx.StaticText(panel,-1,"Tick")
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onTimer, self.timer)
        self.Bind(wx.EVT_CLOSE, self.onExit)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.Text, 0, wx.ALL, 10)
        panel.SetSizer(sizer)
        self.timer.Start(1000) # fire every second
        self.Show()

    def onTimer(self, event):
        if self.Text.GetLabel() == "Tick":
            self.Text.SetLabel("Tock")
        else:
            self.Text.SetLabel("Tick")

    def onExit(self, event):
        self.timer.Stop()
        self.Destroy()

if __name__ == '__main__':
    app = wx.App()
    MyFrame(None,"Tick Tock timer")
    app.MainLoop()