如何在wxPython中以编程方式生成事件
我有一个wxPython的图形界面,我想要通过编程的方式生成一个事件。
我试过这样的写法:
e = wx.Event.__init__(grid, eventType=wx.EVT_LEFT_DOWN)
但是结果是:
TypeError: unbound method __init__() must be called with Event instance as first argument (got Grid instance instead)
或者:
e = wx.CommandEvent(commandType=wx.EVT_BUTTON)
TypeError: in method 'new_CommandEvent', expected argument 1 of type 'wxEventType'
所以我的问题很简单,我需要用什么确切的语法来创建一个事件对象?或者,有没有人能推荐一个好的资源,让我更好地理解事件?我不知道我是不是在理解上漏掉了什么简单的东西。我在网上还没有找到这个问题的直接答案。我查看了这个问题:在wxPython中生成自定义CommandEvent,但我并不想创建一个自定义事件。
提前谢谢大家!
4 个回答
谢谢。@i5on9i 的评论帮了我大忙。
我在Windows下使用WxPython时,想要调用“下一步”按钮。
但是当我尝试用Python的事件时,我的向导程序就直接结束了,仿佛我按下了“完成”按钮,尽管这个按钮在页面上并不可见。
如果我理解得没错,由于这是一个Windows的类(而不是Python的类),我不能使用Python的事件。所以我必须调用Windows的事件。
也许换个方法,从Windows的向导类切换到Python的向导类会更好,但我没有尝试这样做。
顺便说一下,我最终发送的消息是:
win32gui.PostMessage(wizard.GetHandle(),0x0111,wx.ID_FORWARD,self.wizard.FindWindowById(wx.ID_FORWARD).GetHandle())
使用 wx.PostEvent... 可以这样做:
class launcherWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent=None, title='New Window')
#now add the main body, start with a panel
panel = wx.Panel(self)
#instantiate a new dropdown
self.productDropDown = wx.ComboBox(panel, size=wx.DefaultSize, style = wx.CB_READONLY)
#get the products and product subtypes
self.productDict = self.getProductsAndSubtypes()
#setup subtypes first, just in case, since onProductSelection will reference this
self.productSubtypeDropDown = wx.ComboBox(panel, size=wx.DefaultSize, style = wx.CB_READONLY)
#add products
for product in self.productDict.keys():
self.productDropDown.Append(product)
#bind selection event
self.productDropDown.Bind(wx.EVT_COMBOBOX, self.onProductSelection)
#set default selection
self.productDropDown.SetSelection(0)
#pretend that we clicked the product selection, so it's event gets called
wx.PostEvent(self.productDropDown, wx.CommandEvent(wx.wxEVT_COMMAND_COMBOBOX_SELECTED))
#now add the dropdown to a sizer, set the sizer for the panel, fit the panel, etc...
def onProductSelection(self, event):
productSelected = self.productDropDown.GetStringSelection()
productSubtypes = self.productDict[productSelected]
#clear any existing product subtypes, since each product may have different ones
self.productSubtypeDropDown.Clear()
for productSubtype in productSubtypes:
self.productSubtypeDropDown.Append(productSubtype)
#select the first item by default
self.productSubtypeDropDown.SetSelection(0)
你可以使用 wx.PostEvent
来处理事件。
如果你想要程序自动生成一个事件,可以这样做:
wx.PostEvent(self.GetEventHandler(), wx.PyCommandEvent(wx.EVT_BUTTON.typeId, self.GetId()))
如果你想要发送一个 wx.EVT_BUTTON
事件,把它设置为 PyCommandEvent
意味着这个事件会向上传播;而其他类型的事件默认是不会传播的。
使用 wx.PostEvent()
的一般形式是: http://www.wxpython.org/docs/api/wx-module.html#PostEvent
这里有一个简单的示例代码:
import wx
class MyFrame ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Test", pos = wx.DefaultPosition, size = wx.Size( 200,200 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
sizer_inside = wx.BoxSizer( wx.VERTICAL )
# Adding a button and a textCtrl widget
self.button = wx.Button( self, wx.ID_ANY, u"Click Me", wx.DefaultPosition, wx.DefaultSize, 0 )
sizer_inside.Add( self.button, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
self.textCtrl = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_NO_VSCROLL )
sizer_inside.Add( self.textCtrl, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
self.SetSizer( sizer_inside )
self.Layout()
self.Centre( wx.BOTH )
self.Show()
self.counter = 0
# Binding Events
self.Bind( wx.EVT_BUTTON, self.on_click )
self.Bind( wx.EVT_CHOICE, self.test_dummy)
#Event handlers
def on_click( self, event ):
self.counter += 1
wx.PostEvent(self.GetEventHandler(), wx.PyCommandEvent(wx.EVT_CHOICE.typeId, self.GetId()))
def test_dummy(self, event):
self.counter += 1
self.textCtrl.SetValue(str(self.counter))
if __name__ == "__main__":
app = wx.App(False)
MyFrame(None)
app.MainLoop()
如果你运行这个代码,注意到点击按钮后,textCtrl
会显示2。第一个事件处理器手动触发了第二个事件,而这个事件是由 test_dummy
来处理的。