【发布时间】:2010-10-19 08:48:11
【问题描述】:
如何从我自己的代码中手动调用特定事件?
【问题讨论】:
标签: python user-interface events wxpython
如何从我自己的代码中手动调用特定事件?
【问题讨论】:
标签: python user-interface events wxpython
老话题,但我想我在困惑了很长时间后已经弄清楚了,所以如果其他人来这里寻找答案,这可能会有所帮助。
要手动发布事件,您可以使用
self.GetEventHandler().ProcessEvent(event)
(wxWidgets 文档here,wxPython 文档here)
或
wx.PostEvent(self.GetEventHandler(), event)
(wxWidgets docs, wxPython docs)
event 是您要发布的事件。用例如构造事件
wx.PyCommandEvent(wx.EVT_BUTTON.typeId, self.GetId())
如果您想发布 EVT_BUTTON 事件。将其设为PyCommandEvent 意味着它将向上传播;其他事件类型默认不传播。
您还可以创建自定义事件来携带您想要的任何数据。这是一个例子:
myEVT_CUSTOM = wx.NewEventType()
EVT_CUSTOM = wx.PyEventBinder(myEVT_CUSTOM, 1)
class MyEvent(wx.PyCommandEvent):
def __init__(self, evtType, id):
wx.PyCommandEvent.__init__(self, evtType, id)
myVal = None
def SetMyVal(self, val):
self.myVal = val
def GetMyVal(self):
return self.myVal
(我想我在某处的邮件列表存档中找到了此代码,但我似乎无法再次找到它。如果这是您的示例,谢谢!请添加评论并感谢它!)
现在,发布自定义事件:
event = MyEvent(myEVT_CUSTOM, self.GetId())
event.SetMyVal('here is some custom data')
self.GetEventHandler().ProcessEvent(event)
您可以像绑定任何其他事件一样绑定它
self.Bind(EVT_CUSTOM, self.on_event)
并在事件处理程序中获取自定义数据
def on_event(self, e):
data = e.GetMyVal()
print 'custom data is: {0}'.format(data)
或者在事件构造函数中包含自定义数据并保存一个步骤:
class MyEvent(wx.PyCommandEvent):
def __init__(self, evtType, id, val = None):
wx.PyCommandEvent.__init__(self, evtType, id)
self.myVal = val
等等
希望这对某人有所帮助。
【讨论】:
我想你想要wx.PostEvent。
还有一些关于从其他线程为long running tasks on the wxPython wiki 发布事件的信息。
【讨论】:
使用最新版本的 wxPython 有一种简单直接的方法(请参阅 http://wiki.wxpython.org/CustomEventClasses):
# create event class
import wx.lib.newevent
SomeNewEvent, EVT_SOME_NEW_EVENT = wx.lib.newevent.NewEvent()
# post it, with arbitrary data attached
wx.PostEvent(target, SomeNewEvent(attr1=foo, attr2=bar))
# bind it as usual
target.Bind(EVT_SOME_NEW_EVENT, target.handler)
【讨论】:
虽然其他答案中提到的 PostEvent 和 ProcessEvent 等方法可以做到这一点,但请注意它们有很大的局限性:
wx.KeyEvent,因为构造函数不采用键码并且没有设置器。也许有一些解决方法(比如子类化KeyEvent),但你基本上不得不绕过框架的限制。我建议不要在大多数情况下使用PostEvent 或ProcessEvent。如果你只是为了让你的事件处理函数运行,那么手动创建事件是没有意义的;相反,只需显式调用该函数。如果你想要它们是因为你正在尝试编写一个自动化的 UI 测试,那么由于上面列出的限制,你最终可能不会得到满足你的东西;相反,我建议使用wx.UIActionSimulator 在操作系统/桌面管理器级别编写实际模拟点击和按键的内容。这有点恶心,并且会控制您系统的鼠标和键盘,这通常会使此类测试不适合您在开发机器上运行的测试套件......但至少它工作,这是使用PostEvent 调度事件的意义不止于此。
【讨论】:
我想这取决于您的事件与什么相关联,但是当您在列表中选择一个项目时,我需要对显示数据的 LabelFrame 执行相同的操作。这是我能够做到的方式:
'This is the line that binds my function "get_selected_location()"
to the action of selecting an item in my List box.'
self.list1_scoring.bind('<<ListboxSelect>>', self.get_selected_location)
因此,每当您单击“list1_scoring”框中的某个项目时,get_selected_location() 将运行,有关所选项目的详细信息将显示在另一个 LabelFrame 中。我需要在更新过程完成后调用此事件以刷新我的显示窗口。所以我在运行更新的函数末尾添加了这一行。
self.get_selected_location('<<ListboxSelect>>')
这会再次运行 get_selected_location(),就好像我刚刚再次单击了我的列表一样。
【讨论】:
你的意思是你想要一个事件调度?
::wxPostEvent 无效 wxPostEvent(wxEvtHandler *dest, wxEvent&事件)
在 GUI 应用程序中,此函数 将事件发布到指定的目的地 对象使用 wxEvtHandler::AddPendingEvent。 否则,它会分派事件 立即使用 wxEvtHandler::ProcessEvent。见 有关详细信息的相应文档 (和注意事项)。
包含文件
<wx/app.h>
【讨论】: