Prevent focus jump when clicking disabled buttons

Hi! I’m working with a wx.Panel containing multiple buttons, some of which are disabled based on user interaction. The issue I’m facing is that when a user clicks a disabled button, focus seems to jump unexpectedly to the next enabled button in tab order. I’d like to prevent this behavior—ideally, clicking a disabled button should not affect focus at all.

Is there a way to suppress this focus shift or make disabled buttons truly “non-interactive” in that regard? Any suggestions or workarounds would be appreciated!

I’m not seeing the problem you describe when I run the script below using wxPython 4.2.3 gtk3 (phoenix) wxWidgets 3.2.7 + Python 3.12.3 + Linux Mint 22.1

When I click on the disabled ‘Two’ button, the focus stays on the ‘One’ button.

import wx

class ButtonFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, 'Disabled Button',
                          wx.DefaultPosition, (300, 200))
        self.panel = wx.Panel(self)
        button_1 = wx.Button(self.panel, -1, 'One', pos=(20,20))
        button_2 = wx.Button(self.panel, -1, 'Two', pos=(20,60))
        button_3 = wx.Button(self.panel, -1, 'Three', pos=(20,100))
        button_2.Disable()


if __name__ == "__main__":
    app = wx.App()
    frame = ButtonFrame()
    frame.Show()
    app.MainLoop()

Does this example show the problem on your system?

If not, can you post an example that does show the problem?

Thank you for your reply and for the example you provided. I’ve put together a minimal example that demonstrates the issue I’m encountering. Try running it, then click the “the button” button, followed by the “Btn 1” button. You should see the behavior I’m referring to.
import wx
import wx.adv

class MyFrame(wx.Frame):
def init(self, parent, title, rows=4, cols=5):
super().init(parent, title=title, size=(500, 400))

    panel = wx.Panel(self)
    vbox = wx.BoxSizer(wx.VERTICAL)

    # Toolbox with tool buttons
    self.toolbox_panel = wx.Panel(panel)
    hbox = wx.BoxSizer(wx.HORIZONTAL)
    btn = wx.Button(self.toolbox_panel, label='the button')
    btn.Bind(wx.EVT_TOGGLEBUTTON, self.on_tool_selected)
    hbox.Add(btn, 1, wx.ALL|wx.EXPAND, 5)
    self.toolbox_panel.SetSizer(hbox)
    vbox.Add(self.toolbox_panel, 0, wx.EXPAND)

    # Work Area with button matrix
    self.work_panel = wx.Panel(panel)
    self.work_panel.SetFocusIgnoringChildren ()
    grid = wx.GridSizer(rows, cols, 5, 5)
    self.matrix_buttons = []
    for i in range(rows * cols):
        btn = wx.Button(self.work_panel, label=f"Btn {i+1}")
        if i < 3 or i > 10:
            btn.Enable (False)
        btn.Bind(wx.EVT_BUTTON, self.on_matrix_button_clicked)
        grid.Add(btn, 0, wx.EXPAND)
    self.work_panel.SetSizer(grid)
    vbox.Add(self.work_panel, 1, wx.EXPAND | wx.ALL, 5)

    panel.SetSizer(vbox)
    self.Show()

def on_matrix_button_clicked(self, event):
    btn = event.GetEventObject()
    btn.SetLabel('clicked')
def on_tool_selected(self, event):
    pass

class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, title=“example”)
frame.Centre()
return True

if name == “main”:
app = MyApp()
app.MainLoop()

Please can you edit your post so there are three backtick characters (`) before the first line of code, and another 3 backtick characters after the last line of code. That will prevent the forum software from re-formatting it.

I’ve removed them, but your code is looking definitely better than mine. I guess I should know some code formatting tricks…

OK - I tried to unformat your code:

import wx
import wx.adv

class MyFrame(wx.Frame):
    def __init__(self, parent, title, rows=4, cols=5):
        super().__init__(parent, title=title, size=(500, 400))

        panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)

        # Toolbox with tool buttons
        self.toolbox_panel = wx.Panel(panel)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        btn = wx.Button(self.toolbox_panel, label='the button')
        btn.Bind(wx.EVT_TOGGLEBUTTON, self.on_tool_selected)
        hbox.Add(btn, 1, wx.ALL|wx.EXPAND, 5)
        self.toolbox_panel.SetSizer(hbox)
        vbox.Add(self.toolbox_panel, 0, wx.EXPAND)

        # Work Area with button matrix
        self.work_panel = wx.Panel(panel)
        self.work_panel.SetFocusIgnoringChildren ()
        grid = wx.GridSizer(rows, cols, 5, 5)
        self.matrix_buttons = []
        for i in range(rows * cols):
            btn = wx.Button(self.work_panel, label=f"Btn {i+1}")
            if i < 3 or i > 10:
                btn.Enable (False)
            btn.Bind(wx.EVT_BUTTON, self.on_matrix_button_clicked)
            grid.Add(btn, 0, wx.EXPAND)
        self.work_panel.SetSizer(grid)
        vbox.Add(self.work_panel, 1, wx.EXPAND | wx.ALL, 5)

        panel.SetSizer(vbox)
        self.Show()

    def on_matrix_button_clicked(self, event):
        btn = event.GetEventObject()
        btn.SetLabel('clicked')

    def on_tool_selected(self, event):
        pass

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, title="example")
        frame.Centre()
        return True

if __name__ == "__main__":
    app = MyApp()
    app.MainLoop()

When I run it and follow your instructions the focus still doesn’t change when I click on a disabled button.

What OS are you using?
What versions of wxPython and Python?