wx.EVT_SET_FOCUS and wx.EVT_LEFT_DOWN not fired with wx.Choice (wxPython 4.2.0)

Hello,

I am using wxPython 4.2.0 and wxwidgets 1.0.5 with python 3.7.2 on Red Hat 7.
I wanted to modify the wx.Choice list with either wx.EVT_SET_FOCUS or wx.EVT_LEFT_DOWN events.
But unfortunately none of them is fired when clicking on the wx.Choice widget.
I am getting the same issue with python 3.10.4, using the same module versions.

It was working properly on a previous set of versions (wxPython 4.1.1 and wxwidget ??? I don’t remember the older version …).
I don’t have any issue to fire those events with other widgets like wx.TextCtrl.

Any clue or bypass method would be appreciated.

Olivier.

Small example:

import wx

class myFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1)
        panel = wx.Panel(self, -1)
        choice = wx.Choice(panel, choices=['a', 'b', 'c'])
        choice.Bind(wx.EVT_SET_FOCUS, self.onFocus)

    def onFocus(self, event):
        print('fired !')
        event.Skip()

app = wx.App()
myFrame().Show()
app.MainLoop()

Hi,

There is an open bug report for wxWidgets that was raised in 2014:

The last comment (on 2015-12-04) said “Still doesn’t work with the latest sources”. The issue is currently unassigned.

I see @RichardT has got here before me with that link, backed up by EVT_SET_FOCUS and EVT_KILL_FOCUS not working on wx.Choice in wx 3.0 on this very platform.

Best use a wx.ComboBox instead.

Thanks a lot for you replies. I’ll go for a wx.ComboBox so.

Unfortunately, using wx.ComboBox instead of wx.Choice does not solve the issue.

With ComboBox and EVT_LEFT_DOWN:

  • clicking on the arrow does not fire the event (this is where I want the event to be fired)
  • clicking on the ComboBox text fires the event (but as it does not open the list it does not help much …)

With ComboBox and EVT_SET_FOCUS:

  • clicking on the arrow does not fire the event (this is where I want the event to be fired)
  • but the event is fired as soon as I click elsewhere in the Panel

Maybe the arrow part of the widget is accessible and could be the target for the event, but I don’t know how to access it.

import wx

class myFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1)
        panel = wx.Panel(self, -1)
        #choice = wx.Choice(panel, choices=['a', 'b', 'c'])
        self.choice = wx.ComboBox(panel, choices=['a', 'b', 'c'])
        self.choice.Bind(wx.EVT_SET_FOCUS, self.onFocus)
        #self.choice.Bind(wx.EVT_LEFT_DOWN, self.onFocus)

    def onFocus(self, event):
        print(f'fired option {self.choice.GetSelection()}')
        event.Skip()

app = wx.App()
myFrame().Show()
app.MainLoop()

You can bind to EVT_COMBOBOX_DROPDOWN.
I don’t know if you can bend that to your will.

import wx

class myFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1)
        panel = wx.Panel(self, -1)
        #choice = wx.Choice(panel, choices=['a', 'b', 'c'])
        self.choice = wx.ComboBox(panel, choices=['a', 'b', 'c'])
        self.choice.Bind(wx.EVT_COMBOBOX_DROPDOWN, self.onFocus)

    def onFocus(self, event):
        print(f'fired option {self.choice.GetSelection()}')
        event.Skip()

app = wx.App()
myFrame().Show()
app.MainLoop()