According to the docs, dialogs created in wxPython and shown with ShowModal should handle the escape (ESC) key by searching for a button with ID_CANCEL and simulating a click (i.e. triggering its EVT_BUTTON event).
This was working in all but one of my dialogs. After a lot of debugging, I discovered that the cancel button - or any other button! - should have focus. In other words, as long as I call .SetFocus() on one of the buttons I create, the ESC key works fine.
Does anybody know what's going on here? Do dialogs displayed with ShowModal() not automatically get focus? Should they? Or am I misunderstanding something?
In the example code below, uncomment the line b.SetFocus() to see the difference:
import wx
class MainWindow(wx.Frame):
def __init__(self, parent):
super(MainWindow, self).__init__(parent)
self.Show()
d = SomeDialog(self)
d.ShowModal()
self.Destroy()
class SomeDialog(wx.Dialog):
def __init__(self, parent):
super(SomeDialog, self).__init__(parent)
button = wx.Button(self, wx.ID_CANCEL, 'Cancel')
button.Bind(wx.EVT_BUTTON, self.action_cancel)
#button.SetFocus()
def action_cancel(self, e):
self.EndModal(wx.ID_CANCEL)
if __name__ == '__main__':
app = wx.App(False)
frame = MainWindow(None)
app.MainLoop()
Update: This happens when running on linux (Fedora 20, Gnome)
You can call the dialog's SetFocus() method to set focus on itself:
import wx
class MainWindow(wx.Frame):
def __init__(self, parent):
super(MainWindow, self).__init__(parent)
self.Show()
d = SomeDialog(self)
d.ShowModal()
self.Destroy()
class SomeDialog(wx.Dialog):
def __init__(self, parent):
super(SomeDialog, self).__init__(parent)
button = wx.Button(self, wx.ID_CANCEL, 'Cancel')
button.Bind(wx.EVT_BUTTON, self.action_cancel)
self.SetFocus()
def action_cancel(self, e):
self.EndModal(wx.ID_CANCEL)
if __name__ == '__main__':
app = wx.App(False)
frame = MainWindow(None)
app.MainLoop()
This works on Kubuntu 14.04 with wxPython 2.8.12.1 and Python 2.7.6. However, I suspect that when you set focus to the dialog, it is probably passing the focus to its first child just as a wx.Panel will do. I don't know why Linux is behaving in this manner, but I would agree with @nepix32 and @VZ that this should work without the SetFocus(). You can call it anyway as a workaround, but you should probably report it as a bug. There's a link on the wxPython website where you can submit your bug report.