wx.lib.pubsub:如何更改计时器中的值

时间:2014-01-17 13:01:27

标签: python timer wxpython publish-subscribe

您好我有一个问题,计时器设置为1000毫秒,我希望用单选按钮更改该值。以上我有一个示例代码,但我不知道如何做到这一点。是否可以使用wx。 lib.pubsub来改变计时器的值? 有人可以举个例子吗?

以下是代码:

import wx
import time

class SettingsFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY,size=(100,200))
        self.CenterOnParent()
        self.SetBackgroundColour('#e4e4e4')

        self.radio1 = wx.RadioButton(self, label="1 sec",pos=(40,45))
        self.Bind(wx.EVT_RADIOBUTTON, self.SetLab1)

        self.radio2 = wx.RadioButton(self, label="5 sec",pos=(40,65))
        self.Bind(wx.EVT_RADIOBUTTON, self.SetLab2)

        self.radio3 = wx.RadioButton(self, label="10 sec",pos=(40,85))
        self.Bind(wx.EVT_RADIOBUTTON, self.SetLab3)

        extBtn = wx.Button(self, label="Exit",pos=(20,110))
        extBtn.Bind(wx.EVT_BUTTON, self.extFrame)

    def SetLab1(self,event):
        self.Show()
    def SetLab2(self,event):
        self.Show()
    def SetLab3(self,event):
        self.Show

    def extFrame(self,event):
        self.Close()

class MainPanel(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent=parent)
        self.frame = parent
        self.CenterOnParent()

        setBtn = wx.Button(self, label="Set",pos=(45,10))
        setBtn.Bind(wx.EVT_BUTTON, self.setFrame)

        self.redraw_timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)        
        self.redraw_timer.Start(milliseconds=1000)


        def setFrame(self, event):
            SettingsFrame().Show()

        def on_redraw_timer(self, event):
            print "Test: "+time.ctime()

class MainFrame(wx.Frame): 

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY,size=(200,200))
        panel = MainPanel(self)
        self.CenterOnParent()

if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = MainFrame()
    frame.Show()
    app.MainLoop()

2 个答案:

答案 0 :(得分:2)

您的代码存在很多问题。前两个单选按钮绑定到同一个处理程序,即使它们不应该是显而易见的。 SetLab3 没有正确地调用 self.Show ,但是再次在任何这些方法中调用 self.Show 都没有合理。不推荐使用wx.PySimpleApp构造。您现在应该使用wx.App。

现在实际回答问题本身。是的,您可以使用pubsub将信息从SettingFrame传递回MainPanel。以下是如何在wx 2.9 /更新的pubsub中执行此操作:

import wx
import time

from wx.lib.pubsub import pub

class SettingsFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY,size=(100,200))
        self.CenterOnParent()
        self.SetBackgroundColour('#e4e4e4')

        self.radio2 = wx.RadioButton(self, label="1 sec",pos=(40,45))
        self.Bind(wx.EVT_RADIOBUTTON, self.update_timer)

        self.radio2 = wx.RadioButton(self, label="5 sec",pos=(40,65))
        self.Bind(wx.EVT_RADIOBUTTON, self.update_timer)

        self.radio3 = wx.RadioButton(self, label="10 sec",pos=(40,85))
        self.Bind(wx.EVT_RADIOBUTTON, self.update_timer)

        extBtn = wx.Button(self, label="Exit",pos=(20,110))
        extBtn.Bind(wx.EVT_BUTTON, self.extFrame)

        self.choice = 1

    #----------------------------------------------------------------------
    def update_timer(self, event):
        """"""
        ctrl = event.GetEventObject()
        if ctrl.GetLabel() == "1 sec":
            self.choice = 1000
        elif ctrl.GetLabel() == "5 sec":
            self.choice = 5000
        elif ctrl.GetLabel() == "10 sec":
            self.choice = 10000

    def extFrame(self,event):
        pub.sendMessage("update_timer", message=self.choice)
        self.Close()

class MainPanel(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent=parent)
        self.frame = parent
        self.CenterOnParent()

        setBtn = wx.Button(self, label="Set",pos=(45,10))
        setBtn.Bind(wx.EVT_BUTTON, self.setFrame)

        self.redraw_timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)        
        self.redraw_timer.Start(milliseconds=1000)

        pub.subscribe(self.listener, "update_timer")

    def setFrame(self, event):
        SettingsFrame().Show()

    def on_redraw_timer(self, event):
        print "Test: "+time.ctime()

    def listener(self, message, arg2=None):
        self.redraw_timer.Stop()
        self.redraw_timer.Start(message)

class MainFrame(wx.Frame): 

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY,size=(200,200))
        panel = MainPanel(self)
        self.CenterOnParent()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MainFrame()
    frame.Show()
    app.MainLoop()

请注意,此示例也会清除您的代码。你可以在这里阅读更多关于pubsub的信息:

您可能还会发现此计时器教程很有用:

答案 1 :(得分:1)

非pubsub版本

向MainPanel添加更改计时器方法,以更改计时器的起始值

创建SettingsFrame时,将MainPanel实例的ref传递给它。

将Ref存储到SettingsFrame上的父级。

中纠正RadioButton 1
self.radio2

self.radio1.

更改绑定,以便它们像这样

绑定到单选按钮本身
self.radio1.Bind(wx.EVT_RADIOBUTTON, self.SetLab1)

在事件句柄中,使用新值

调用父更改计时器方法
self.parent.change_timer(1000)

以下是完整代码,以防我可能错过了我所做的更改的其中一个步骤

import wx
import time


class SettingsFrame(wx.Frame):

    def __init__(self, parent):
        wx.Frame.__init__(self, None, wx.ID_ANY, size=(100, 200))
        self.parent = parent
        self.CenterOnParent()
        self.SetBackgroundColour('#e4e4e4')

        self.radio1 = wx.RadioButton(self, label="1 sec", pos=(40, 45))
        self.radio1.Bind(wx.EVT_RADIOBUTTON, self.SetLab1)

        self.radio2 = wx.RadioButton(self, label="5 sec", pos=(40, 65))
        self.radio2.Bind(wx.EVT_RADIOBUTTON, self.SetLab2)

        self.radio3 = wx.RadioButton(self, label="10 sec", pos=(40, 85))
        self.radio3.Bind(wx.EVT_RADIOBUTTON, self.SetLab3)

        extBtn = wx.Button(self, label="Exit", pos=(20, 110))
        extBtn.Bind(wx.EVT_BUTTON, self.extFrame)

    def SetLab1(self, event):
        self.parent.change_timer(1000)

    def SetLab2(self, event):
        self.parent.change_timer(5000)

    def SetLab3(self, event):
        self.parent.change_timer(10000)

    def extFrame(self, event):
        self.Close()


class MainPanel(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent=parent)
        self.frame = parent
        self.CenterOnParent()

        setBtn = wx.Button(self, label="Set", pos=(45, 10))
        setBtn.Bind(wx.EVT_BUTTON, self.setFrame)

        self.redraw_timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)
        self.redraw_timer.Start(milliseconds=1000)

    def setFrame(self, event):
        SettingsFrame(self).Show()

    def on_redraw_timer(self, event):
        print "Test: " + time.ctime()

    def change_timer(self, value):
        print 'Changing timer to:', value
        self.redraw_timer.Start(value)


class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, size=(200, 200))
        panel = MainPanel(self)
        self.CenterOnParent()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MainFrame()
    frame.Show()
    app.MainLoop()

使用自定义活动

这是使用从MainPanel可以绑定到的SettingsFrame发送的自定义事件的另一种方法。

import time

import wx
from wx.lib.newevent import NewCommandEvent


TimerChangeEvent, EVT_TIMER_CHANGE = NewCommandEvent()


class SettingsFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, size=(100, 200))
        self.CenterOnParent()
        self.SetBackgroundColour('#e4e4e4')

        self.radio1 = wx.RadioButton(self, label="1 sec", pos=(40, 45))
        self.radio1.Bind(wx.EVT_RADIOBUTTON, self.SetLab1)

        self.radio2 = wx.RadioButton(self, label="5 sec", pos=(40, 65))
        self.radio2.Bind(wx.EVT_RADIOBUTTON, self.SetLab2)

        self.radio3 = wx.RadioButton(self, label="10 sec", pos=(40, 85))
        self.radio3.Bind(wx.EVT_RADIOBUTTON, self.SetLab3)

        extBtn = wx.Button(self, label="Exit", pos=(20, 110))
        extBtn.Bind(wx.EVT_BUTTON, self.extFrame)

    def SetLab1(self, event):
        self.post_timer_change_event(1000)

    def SetLab2(self, event):
        self.post_timer_change_event(5000)

    def SetLab3(self, event):
        self.post_timer_change_event(10000)

    def post_timer_change_event(self, value):
        evt = TimerChangeEvent(self.Id, value=value)
        wx.PostEvent(self, evt)

    def extFrame(self, event):
        self.Close()


class MainPanel(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent=parent)
        self.frame = parent
        self.CenterOnParent()

        setBtn = wx.Button(self, label="Set", pos=(45, 10))
        setBtn.Bind(wx.EVT_BUTTON, self.setFrame)

        self.redraw_timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)
        self.redraw_timer.Start(milliseconds=1000)

    def setFrame(self, event):
        settings_frame = SettingsFrame()
        settings_frame.Show()
        settings_frame.Bind(EVT_TIMER_CHANGE, self.on_change_timer)

    def on_redraw_timer(self, event):
        print "Test: " + time.ctime()

    def on_change_timer(self, event):
        value = event.value
        print 'Changing timer to:', value
        self.redraw_timer.Start(value)


class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, size=(200, 200))
        panel = MainPanel(self)
        self.CenterOnParent()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MainFrame()
    frame.Show()
    app.MainLoop()