如果在事件处理程序中调用wx.PostEvent不会触发事件?

问题描述:

我想在Ubuntu 14.04,MATE桌面,python 2.7,python-wxgtk2.8 2.8.12.1下面发布的代码为combotest.py;该应用程序是这样的:如果在事件处理程序中调用wx.PostEvent不会触发事件?

combotest

当我点击下拉框,直接改变它,相应的事件处理程序OnUpdateComboBox火灾,我得到这个印在标准输出:

OnUpdateComboBox <wx._controls.ComboBox; proxy of <Swig Object of type 'wxComboBox *' at 0x909caf0> > MyComboBox 

我请注意:

http://wxpython-users.1045709.n5.nabble.com/SetValue-on-spinctrl-doesn-t-send-update-event-td2289628.html

一般政策是,用户 对控件值所做的更改会生成事件并且编程方式进行的更改不会生成。所以,你应该上的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() 
+0

这一点是我刚刚通过直接调用处理器周围的工作 - 确认在最新的凤凰开发版本 – user2682863

+0

我的答案是否解决了你的问题? – user2682863

请不要直接调用事件处理函数 - 尤其是这样。 更好的解决办法是要创造将执行时需要在组合框中的值更改,并从两个处理器调用这个函数做任何意愿的功能。

而且,这将是很好知道,如果一切都在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()编辑时指的是光标位置,而不是最后的选择