3

我正在尝试学习如何在主 GUI 应用程序之外运行一个线程来执行我的串行端口发送/接收,同时保持我的 GUI 活动。我最好的谷歌搜索让我登陆了 wxpython wiki:http ://wiki.wxpython.org/LongRunningTasks,它提供了几个示例。我已经决定学习第一个示例,涉及在选择特定按钮时启动工作线程。

我无法理解自定义事件定义:

def EVT_RESULT(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_RESULT_ID, func)

class ResultEvent(wx.PyEvent):
    """Simple event to carry arbitrary result data."""
    def __init__(self, data):
        """Init Result Event."""
        wx.PyEvent.__init__(self)
        self.SetEventType(EVT_RESULT_ID)
        self.data = data

主要是

def EVT_RESULT(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_RESULT_ID, func)

我认为 EVT_RESULT 放在类之外,以便两个类都可以调用它(使其成为全局?)

并且.. 主 GUI 应用程序通过以下方式监视线程的进度:

# Set up event handler for any worker thread results
EVT_RESULT(self,self.OnResult)

我还注意到,在很多例子中,当作者使用

from wx import *

他们只是通过以下方式绑定事物

EVT_SOME_NEW_EVENT(self, self.handler)

wx.Bind(EVT_SOME_NEW_EVENT, self.handler)

这并不能帮助我更快地理解它。谢谢,

4

3 回答 3

4

这是定义自定义事件的旧风格。有关详细信息,请参阅迁移指南

取自迁移指南:

如果您创建自己的自定义事件类型和 EVT_* 函数,并且希望能够将它们与上面的 Bind 方法一起使用,那么您应该将 EVT_* 更改为实例wx.PyEventBinder而不是函数。例如,如果你曾经有过这样的事情:

myCustomEventType = wxNewEventType()
def EVT_MY_CUSTOM_EVENT(win, id, func):
    win.Connect(id, -1, myCustomEventType, func)

像这样改变它:

myCustomEventType = wx.NewEventType()
EVT_MY_CUSTOM_EVENT = wx.PyEventBinder(myCustomEventType, 1)

这是我使用几个示例程序制作的另一篇文章,这些示例程序完全符合您的要求。

于 2010-02-27T00:39:22.803 回答
2

您可以像这样定义事件:

from wx.lib.newevent import NewEvent

ResultEvent, EVT_RESULT = NewEvent()

您像这样发布事件:

wx.PostEvent(handler, ResultEvent(data=data))

像这样绑定它:

def OnResult(event):
    event.data

handler.Bind(EVT_RESULT, OnResult)

但是如果你只需要从主线程中的非主线程进行调用,你可以使用wx.CallAfter这里有一个例子。

当您不想硬编码谁负责什么时,自定义事件很有用(请参阅观察者设计模式)。例如,假设您有一个主窗口和几个子窗口。假设当主窗口发生某种变化时,需要刷新一些子窗口。在这种情况下,主窗口可以直接刷新这些子窗口,但更优雅的方法是定义一个自定义事件并让主窗口将其发布给自己(而不用打扰谁需要对其做出反应)。然后需要对该事件做出反应的孩子可以通过绑定到它自己来完成(如果有多个,那么他们调用很重要,event.Skip()以便调用所有绑定的方法)。

于 2010-02-27T09:41:54.107 回答
0

您可能想要使用 Python 线程和队列,而不是自定义事件。我有一个 wxPython 程序 ( OpenSTV ),它加载导致 gui 在加载过程中冻结的大文件。为了防止冻结,我调度了一个线程来加载文件并使用队列在 gui 和线程之间进行通信(例如,将异常传达给 GUI)。

  def loadBallots(self):
    self.dirtyBallots = Ballots()
    self.dirtyBallots.exceptionQueue = Queue(1)
    loadThread = Thread(target=self.dirtyBallots.loadUnknown, args=(self.filename,))
    loadThread.start()

    # Display a progress dialog
    dlg = wx.ProgressDialog(\
      "Loading ballots",
      "Loading ballots from %s\nNumber of ballots: %d" % 
      (os.path.basename(self.filename), self.dirtyBallots.numBallots),
      parent=self.frame, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME
    )
    while loadThread.isAlive():
      sleep(0.1)
      dlg.Pulse("Loading ballots from %s\nNumber of ballots: %d" %
                (os.path.basename(self.filename), self.dirtyBallots.numBallots))
    dlg.Destroy()

if not self.dirtyBallots.exceptionQueue.empty():
  raise RuntimeError(self.dirtyBallots.exceptionQueue.get())
于 2010-03-01T21:33:30.583 回答