wx.Dialog中的ESC键不会触发ID_CANCEL按钮,除非该按钮获得焦点
根据文档,在wxPython中创建的对话框,如果用ShowModal显示,应该能处理ESC键。它的做法是找一个ID为ID_CANCEL的按钮,然后模拟点击这个按钮,也就是触发它的EVT_BUTTON事件。
这个功能在我所有的对话框中都能正常工作,除了一个。经过大量的调试,我发现取消按钮,或者说任何一个按钮,都需要获得焦点。换句话说,只要我在我创建的按钮上调用.SetFocus(),那么ESC键就能正常工作了。
有没有人知道这是怎么回事?用ShowModal()显示的对话框是不是不会自动获得焦点?应该获得吗?还是我理解错了什么?
在下面的示例代码中,取消注释b.SetFocus()那一行,就能看到区别:
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()
更新:这个问题在linux(Fedora 20,Gnome)上出现。
1 个回答
2
你可以调用对话框的 SetFocus() 方法来让它自己获得焦点:
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()
这个方法在 Kubuntu 14.04 系统上,使用 wxPython 2.8.12.1 和 Python 2.7.6 时是有效的。不过,我怀疑当你把焦点设置到对话框时,它可能会把焦点传递给它的第一个子控件,就像 wx.Panel 一样。我不太明白为什么 Linux 会这样表现,但我同意 @nepix32 和 @VZ 的看法,这个功能应该在不使用 SetFocus() 的情况下也能正常工作。你可以把它当作一种解决方法来调用,但你可能应该把这个问题报告为一个bug。在 wxPython 网站上有一个链接,你可以在那提交你的bug报告。