【问题标题】:Is there a way to send an event to wxApp?有没有办法向 wxApp 发送事件?
【发布时间】:2021-03-15 11:00:22
【问题描述】:

我将 wxPython 用于 GUI,并且我有一个与某些 I/O 交互的不同线程。当线程从 I/O 设备接收到事件时,有没有办法更新 GUI 以显示 I/O 状态? 更清楚一点:IOthread 每 3 秒询问一次停车栏是向上还是向下,我希望 GUI 在向下或向上时显示红色 LED 或绿色 LED。所以基本上我需要将 IOthread 接收到的信息传达给在主线程中运行的 GUI

【问题讨论】:

    标签: multithreading wxpython


    【解决方案1】:

    您可以查看pubsub,但由于您正在使用带有线程的wxPython,因此使用用户定义的event 会更容易。
    这个改编的代码只是在 True 和 False 之间交替,显然你会改变它并且只发布事件,如果它改变了。

    from threading import Thread
    import wx
    import time
    import wx.lib.newevent
    
    progress_event, EVT_PROGRESS_EVENT = wx.lib.newevent.NewEvent()
    
    class WorkThread(Thread):
    
        def __init__(self,parent_target):
            """Init Worker Thread Class."""
            Thread.__init__(self)
            self.target = parent_target
            self.stop_work_thread = 0
            self.start()  # start the thread
    
        def run(self):
            curr_loop = True
            while True:
                if self.stop_work_thread == 1: # Exit
                    break
                time.sleep(1)
                if self.stop_work_thread == 2: # Paused
                    continue
                curr_loop = not curr_loop
                evt = progress_event(active=curr_loop,name=self.name)
                #Send back current bar position up True, Down False
                try:
                    wx.PostEvent(self.target, evt)
                except: # The parent frame has probably been destroyed
                    self.stop()
            return
    
        def stop(self):
            self.stop_work_thread = 1
    
        def pause(self):
            if self.stop_work_thread == 2:
                self.stop_work_thread = 0
                self.target.pause_btn.SetLabel('Pause')
            else:
                self.stop_work_thread = 2
                self.target.pause_btn.SetLabel('Paused')
    
    class Progress(wx.Frame):
        def __init__(self, parent, title):
            super(Progress, self).__init__(parent, title = title,size = (500,300))
            left_sizer = wx.BoxSizer(wx.VERTICAL)
            middle_sizer = wx.BoxSizer(wx.HORIZONTAL)
            self.panel = wx.Panel(self)
    
            self.start_btn = wx.Button(self.panel, label="Start")
            self.stop_btn =wx.Button(self.panel, label="Stop")
            self.pause_btn =wx.Button(self.panel, label="Pause")
            self.quit_btn =wx.Button(self.panel, label="Quit")
            self.logger = wx.TextCtrl(self.panel, size=(200,200), style=wx.TE_MULTILINE | wx.TE_READONLY)
    
            self.stop_btn.Disable()
            self.pause_btn.Disable()
            left_sizer.Add(self.start_btn,0,wx.EXPAND)
            left_sizer.Add(self.stop_btn,0,wx.EXPAND)
            left_sizer.Add(self.pause_btn,0,wx.EXPAND)
            left_sizer.Add(self.quit_btn,0,wx.EXPAND)
            middle_sizer.Add(self.logger,0,wx.EXPAND)
            self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
            self.mainsizer.Add(left_sizer)
            self.mainsizer.Add(middle_sizer)
            self.panel.SetSizer(self.mainsizer)
            self.Layout()
    
            self.start_btn.Bind(wx.EVT_BUTTON, self.onStart)
            self.stop_btn.Bind(wx.EVT_BUTTON, self.onCancel)
            self.pause_btn.Bind(wx.EVT_BUTTON, self.onPause)
            self.quit_btn.Bind(wx.EVT_BUTTON, self.onExit)
            #Bind to the progress event issued by the thread
            self.Bind(EVT_PROGRESS_EVENT, self.OnActive)
            self.Bind(wx.EVT_CLOSE, self.onExit)
    
        def OnActive(self, event):
            if not self.work.is_alive():
                return 
            active = event.active
            ident = event.name
            if active:
                self.logger.Clear()
                self.logger.SetBackgroundColour("green")
                self.logger.write('\n\n\n\n\n\t\tBar is Up')
            else:
                self.logger.Clear()
                self.logger.SetBackgroundColour("red")
                self.logger.write('\n\n\n\n\n\t\tBar is Down')
    
        def onStart(self, event):
            self.start_btn.Disable()
            self.work = WorkThread(parent_target=self)
            self.pause_btn.Enable()
            self.stop_btn.Enable()
    
        def onPause(self, event):
            if self.work.is_alive():
                self.work.pause() # Pause the thread
    
        def onCancel(self, event):
            """Cancel thread process"""
            try:
                self.work.stop()
                self.work.join()
            except:
                pass
            self.onFinish()
    
        def onFinish(self):
            """thread process finished - clean up"""
            self.start_btn.Enable()
            self.stop_btn.Disable()
            self.pause_btn.Disable()
            self.pause_btn.SetLabel("Pause")
            self.logger.Clear()
            self.logger.SetBackgroundColour("white")
    
        def onExit(self, event):
            self.onCancel(None)
            self.onFinish()
            self.Destroy()
    
    app = wx.App()
    frame = Progress(None,'Bar Up/Down Display')
    frame.Show()
    app.MainLoop()
    

    【讨论】:

    • 谢谢,这正是我要找的!
    猜你喜欢
    • 2015-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 2019-06-13
    • 1970-01-01
    相关资源
    最近更新 更多