wxPython:手动调用事件

时间:2009-04-14 14:14:27

标签: python user-interface events wxpython

如何从我自己的代码手动调用特定事件?

6 个答案:

答案 0 :(得分:53)

老话题,但我想我已经弄好了很长一段时间后弄清楚这个问题,所以如果有其他人来这里寻找答案,这可能会有所帮助。

要手动发布活动,您可以使用

self.GetEventHandler().ProcessEvent(event)

(wxWidgets docs here,wxPython docs here

wx.PostEvent(self.GetEventHandler(), event)

wxWidgets docswxPython 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

希望这对某人有帮助。

答案 1 :(得分:11)

我想你想要wx.PostEvent

还有一些关于从long running tasks on the wxPython wiki的其他帖子发布事件的信息。

答案 2 :(得分:5)

使用最新版本的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)

答案 3 :(得分:1)

在其他答案中提到的@TestInstance(Lifecycle.PER_CLASS)A之类的方法可以做到这一点,请注意它们有很大的局限性:

  • 您受限于可以轻松创建的事件。例如,无法使用特定的键代码创建B,因为构造方法不使用键代码,也没有设置方法。也许有一些解决方法(例如子类PostEvent),但实际上您必须克服框架的局限性。
  • 即使对于您可以创建的事件(例如单击事件),您通过以编程方式调度该事件而获得的行为与您实际以用户身份执行该操作所获得的行为也不匹配,因为事件的 native 处理不会触发。例如,以编程方式触发文本字段上的click事件不会使文本字段成为焦点。

在大多数情况下,建议不要使用ProcessEventwx.KeyEvent。如果只是使事件处理功能运行,那么手动创建事件是没有意义的。而是直接显式调用该函数。如果由于尝试编写自动UI测试而需要它们,那么由于上面列出的限制,您可能最终不会满意。相反,我建议您使用wx.UIActionSimulator在OS /桌面管理器级别编写实际上模拟点击和按键的东西。这有点麻烦,并且可以控制系统的鼠标和键盘,这通常会使此类测试不适合您在开发机上运行的测试套件...但是至少它能正常工作,用KeyEvent调度事件比说的要多。

答案 4 :(得分:0)

你的意思是你想要发送一个事件?

  

:: wxPostEvent无效   wxPostEvent(wxEvtHandler * dest,   wxEvent&安培;事件)

     

在GUI应用程序中,此功能   将事件发布到指定的dest   对象使用   wxEvtHandler :: AddPendingEvent。   否则,它会调度事件   立即使用   wxEvtHandler :: processEvent方法。见   各自的文件详情   (和警告)。

     

包含文件

     

<wx/app.h>

wxPython API docs

答案 5 :(得分:0)

我想这取决于你的事件与你的事情有关,但我需要对你在List中选择一个项目时显示数据的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(),好像我刚刚再次点击了我的列表。