我正在尝试学习如何从主GUI应用程序运行一个线程来执行我的串口发送/接收,同时保持我的GUI活着。我最好的谷歌搜索尝试让我登上了http://wiki.wxpython.org/LongRunningTasks的wxpython wiki,它提供了几个例子。我已经决定学习第一个例子,包括在选择特定按钮时启动工作线程。
我无法理解自定义事件定义:
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)
这不能帮助我更快地理解它。 谢谢,
答案 0 :(得分:4)
这是定义自定义事件的旧方式。有关详细信息,请参阅the migration guide。
摘自迁移指南:
如果您创建自己的自定义事件 类型和EVT_ *函数,以及您 希望能够与它们一起使用 你应该在上面绑定方法 将您的EVT_ *更改为
wx.PyEventBinder
的实例,而不是a 功能。例如,如果你曾经 有这样的事情: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)
Here is another post我使用了几个完全符合您要求的示例程序。
答案 1 :(得分:3)
您可以定义如下事件:
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
,here就是一个例子。
当您不想硬编码负责什么的人时,自定义事件非常有用(请参阅observer design pattern)。例如,假设您有一个主窗口和几个子窗口。假设当主窗口发生某种变化时,需要刷新一些子窗口。在这种情况下,主窗口可以直接刷新那些子窗口,但更优雅的方法是定义自定义事件并让主窗口将其发布到自身(并且不需要对需要对其作出反应的麻烦)。那么需要对该事件做出反应的孩子可以通过绑定它来自己做(如果不止一个,重要的是他们调用event.Skip()
以便调用所有绑定的方法。 / p>
答案 2 :(得分: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())