如果在事件处理程序中调用wx.PostEvent不会触发事件?
我想在Ubuntu 14.04,MATE桌面,python 2.7,python-wxgtk2.8 2.8.12.1下面发布的代码为combotest.py
;该应用程序是这样的:如果在事件处理程序中调用wx.PostEvent不会触发事件?
当我点击下拉框,直接改变它,相应的事件处理程序OnUpdateComboBox
火灾,我得到这个印在标准输出:
OnUpdateComboBox <wx._controls.ComboBox; proxy of <Swig Object of type 'wxComboBox *' at 0x909caf0> > MyComboBox
我请注意:
一般政策是,用户 对控件值所做的更改会生成事件并且编程方式进行的更改不会生成。所以,你应该上的SetValue 计划不发送的情况下,
我想有选择变了 - 和相应的处理程序解雇 - 在组合框中,单击该按钮时。并且如WxPython - trigger checkbox event while setting its value in the code中所建议的那样,因此,我试图调用wx.PostEvent()
来强制组合框事件处理程序的调用,一旦其按钮代码以编程方式更改其选择。
当我按一下按钮,我可以看到它的处理器BtnClickHandler
不会被调用,如预期,它改变了组合框选择一个新的项目 - 但是,调用wx.PostEvent()
,如果不管它是独立的或wx.CallAfter()
,根本就不曾请拨打OnUpdateComboBox
。
那么,如何在通过按钮事件处理程序以编程方式更改其选择时调用组合框事件处理程序?或者这是一个错误?
编辑:原来我可以直接调用该函数,所以在BtnClickHandler
我可以这样做:
self.OnUpdateComboBox(oevt)
...然后处理程序将调用 - 但有些事情感觉不对这个...
此外,任何想法,为什么self.combo_box.GetLastPosition()
回报2,即使在组合框中5个项目?!
combotest.py
import wxversion
wxversion.select("2.8")
import wx, wx.html
import sys
class Frame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.label = wx.StaticText(self, wx.ID_ANY, "Click the button to change combobox below: ")
self.bt_main = wx.Button(self, label="Click ME")
self.bt_main.Bind(wx.EVT_BUTTON, self.BtnClickHandler)
self.combo_box = wx.ComboBox(self, wx.ID_ANY, choices=["AAA", "BBB", "CCC", "DDD", "EEE"], style=wx.CB_DROPDOWN | wx.CB_READONLY, name="MyComboBox")
self.combo_box.SetSelection(0) # this does not call event
wx.PostEvent(self.combo_box, wx.CommandEvent(wx.EVT_COMBOBOX.typeId)) #neither does this
self.Bind(wx.EVT_COMBOBOX, self.OnUpdateComboBox, self.combo_box)
sizer_vmain_app = wx.BoxSizer(wx.VERTICAL)
sizer_vmain_app.Add(self.label, proportion=0, flag=wx.EXPAND, border=0)
sizer_vmain_app.Add(self.bt_main, proportion=0, flag=0, border=0)
sizer_vmain_app.Add(self.combo_box, proportion=0, flag=0, border=0)
self.SetSizer(sizer_vmain_app)
self.Layout()
def OnUpdateComboBox(self, event):
widget = event.GetEventObject()
print("OnUpdateComboBox " + repr(widget) + " " + widget.GetName())
def BtnClickHandler(self, event):
print("BtnClickHandler " + repr(self.combo_box.GetLastPosition()))
newsel = (self.combo_box.GetSelection() + 1) % (self.combo_box.GetLastPosition()+1) # GetLastPosition is 2, even with 5 items in box?!
self.combo_box.SetSelection(newsel) # this does not call event
oevt = wx.CommandEvent(commandType=wx.EVT_COMBOBOX.typeId)
oevt.SetEventObject(self.combo_box)
wx.PostEvent(self.combo_box, oevt) # does nothing
wx.CallAfter(wx.PostEvent, self.combo_box, oevt) # does nothing
if __name__ == "__main__":
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
app_frame = Frame(None, wx.ID_ANY, "")
app.SetTopWindow(app_frame)
app_frame.Show()
app.MainLoop()
请不要直接调用事件处理函数 - 尤其是这样。 更好的解决办法是要创造将执行时需要在组合框中的值更改,并从两个处理器调用这个函数做任何意愿的功能。
而且,这将是很好知道,如果一切都在WX-3.0/3.1的作品。
好吧我想出了一个解决方案。直接绑定到组合框而不是框架。这是一个工作示例(wx phoenix 3.03.xyz dev ....)
class Frame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.label = wx.StaticText(self, wx.ID_ANY, "Click the button to change combobox below: ")
self.bt_main = wx.Button(self, label="Click ME")
self.bt_main.Bind(wx.EVT_BUTTON, self.BtnClickHandler)
self.combo_box = wx.ComboBox(self, wx.ID_ANY, choices=["AAA", "BBB", "CCC", "DDD", "EEE"],
style=wx.CB_DROPDOWN | wx.CB_READONLY, name="MyComboBox")
# self.Bind(wx.EVT_COMBOBOX, self.OnUpdateComboBox, self.combo_box)
# bind directly to the widget
self.combo_box.Bind(wx.EVT_COMBOBOX, self.OnUpdateComboBox)
self.combo_box.SetSelection(0)
combo_event = wx.CommandEvent(wx.EVT_COMBOBOX.typeId)
combo_event.SetEventObject(self.combo_box)
wx.PostEvent(self.combo_box, combo_event)
sizer_vmain_app = wx.BoxSizer(wx.VERTICAL)
sizer_vmain_app.Add(self.label, proportion=0, flag=wx.EXPAND, border=0)
sizer_vmain_app.Add(self.bt_main, proportion=0, flag=0, border=0)
sizer_vmain_app.Add(self.combo_box, proportion=0, flag=0, border=0)
self.SetSizer(sizer_vmain_app)
self.Layout()
def OnUpdateComboBox(self, event):
widget = event.GetEventObject()
print("OnUpdateComboBox " + repr(widget) + " " + widget.GetName())
def BtnClickHandler(self, event):
print("BtnClickHandler " + repr(self.combo_box.GetLastPosition()))
newsel = (self.combo_box.GetSelection() + 1) % (
self.combo_box.GetLastPosition() + 1) # GetLastPosition is 2, even with 5 items in box?!
self.combo_box.SetSelection(newsel) # this does not call event
oevt = wx.CommandEvent(commandType=wx.EVT_COMBOBOX.typeId)
oevt.SetEventObject(self.combo_box)
wx.PostEvent(self.combo_box, oevt) # does nothing
wx.CallAfter(wx.PostEvent, self.combo_box, oevt) # does nothing
if __name__ == "__main__":
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
app_frame = Frame(None, wx.ID_ANY, "")
app.SetTopWindow(app_frame)
app_frame.Show()
app.MainLoop()
旁注
self.combox_box.GetLastPosition()
编辑时指的是光标位置,而不是最后的选择
这一点是我刚刚通过直接调用处理器周围的工作 - 确认在最新的凤凰开发版本 – user2682863
我的答案是否解决了你的问题? – user2682863