有没有办法向 wxApp 发送事件?

Is there a way to send an event to wxApp?

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

您可以看一下 pubsub,但是当您将 wxPython 与线程一起使用时,使用用户定义的 event.
会更容易 这个改编的代码,只是在 True 和 False 之间交替,显然你会改变它并且只有 post 事件,如果它改变了。

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