wx.EVT_COMBOBOX event and GetSelection method odd behavior

It is known that in wxpython setting in the code the value of a combobox doesn’t trigger the EVT_COMBOBOX event as instead it does when the user select an item with the mouse. So, if needed, you have to trigger manually the event.

In my program, in the handler function, I need to use the value returned by the method event.GetSelection(), where event is the event object passed in to the handler function.

Now, the problem is that if I set in the code the value of the combo box and then trigger manually the EVT_COMBOBOX event, the method event.GetSelection() doesn’t return the same value as if the event was rised by the user selecting the same item with the mouse.

The problem is shown by the following code. As you can see, when the event is triggered by the code, the event.GetSelection() method returns always the value 0 (i.e. the first item in the combo box list) instead of the value 1 setted in the code.

Why this happen?


import wx

class ManualEventFrame(wx.Frame):

    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, 'Manual Event Rising',size=(550, 200))
        self.panel = wx.Panel(self)
        self.st=wx.StaticText(self.panel, label='Select an item', pos=(10,10))
        self.cb=wx.ComboBox(self.panel,pos=(110,10),choices=['a','b','c'])
        self.st2 = wx.StaticText(self.panel, label='You choosed item', pos=(10, 75))
        self.tc=wx.TextCtrl(self.panel,pos=(110,75))
        self.button = wx.Button(self.panel,label="Select item 'b' and rise\nmanually the EVT_COMBOBOX event", pos=(300, 40))

        self.button.Bind(wx.EVT_BUTTON,self.onButton)
        self.cb.Bind(wx.EVT_COMBOBOX, self.onSelect)

    def onSelect(self,event):
        self.tc.SetValue(self.cb.GetString(event.GetSelection()))
    def onButton(self, event):
        self.cb.SetSelection(1)
        myevent = wx.CommandEvent(wx.EVT_COMBOBOX._getEvtType(), self.cb.GetId())
        myevent.SetEventObject(self.cb)
        self.cb.GetEventHandler().ProcessEvent(myevent)


if __name__ == '__main__':
    app = wx.App()
    frame = ManualEventFrame(parent=None, id=-1)
    frame.Show()
    app.MainLoop()

You would need to set the other attributes of the wx.CommandEvent if you want to to fully emulate the functionality of the event. However there are better and simpler ways to handle things like this.

For example, you can refactor your code such that there is a third method that is called by both onSelect and onButton and which does the actual work. Maybe something like this:

    def doOnSelect(self, selection):
        self.tc.SetValue(self.cb.GetString(selection))
    
    def onSelect(self,event):
        self.doOnSelect(event.GetSelection()))

    def onButton(self, event):
        self.cb.SetSelection(1)
        self.doOnSelect(1)
1 Like

Hi Robin, thank you very much for your precious suggestions. I suspected that the problem was in that ‘misterious’ event object and his many attributes. I don’t know how to set them for each event type in order to emulate the event I want to trigger. I went through the documentation but didn’t find the full structure of the event object.