我正在Ubuntu 14.04上尝试下面发布的代码为combotest.py
,MATE桌面,python 2.7,python-wxgtk2.8 2.8.12.1;应用程序是这样的:
当我点击组合框并直接更改它时,会触发相应的事件处理程序OnUpdateComboBox
,并在stdout上打印出来:
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)
...然后处理程序将被调用 - 但有些事情对此感觉不正确......
此外,即使组合框中有5个项目,self.combo_box.GetLastPosition()
返回2的任何想法都会出现?!
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 :(得分:0)
请不要直接调用事件处理函数 - 尤其是这样。 更好的解决方案是创建一个函数,该函数将执行组合框中的值更改时需要执行的任何操作,并从两个处理程序中调用此函数。
另外,如果知道wx-3.0 / 3.1中的所有内容是否都能正常工作,那就太好了。
答案 1 :(得分:0)
好的我找到了解决方案。直接绑定到组合框而不是框架。这是一个工作示例(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()
指的是编辑时的光标位置,而不是最后一个选择