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?