wxPython:菜单快捷键的作用域与动态禁用
我在 Arch Linux x86_64 上使用 Python 2.7.2 和 wxPython 2.8.12.1。
我想让下面这个例子这样工作:
* 当左边的文本框(text_A
)有焦点时,按下 Shift+A
应该执行 do_A()
,而按下 Shift+B
应该在文本区域写入 B
;同时,menu.foo.bar_B
应该被禁用(而 menu.foo.bar_A
应该被启用)
* 当右边的文本框(text_B
)有焦点时,按下 Shift+A
应该在文本区域写入 A
,而按下 Shift+B
应该执行 do_B()
;同时,menu.foo.bar_A
应该被禁用(而 menu.foo.bar_B
应该被启用)
import wx
class Foo(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, size=(600, 480))
self.init_menu()
self.init_text()
self.Centre()
self.Show(True)
def init_menu(self):
self.menu = wx.MenuBar()
self.SetMenuBar(self.menu)
self.menu.foo = wx.Menu()
self.menu.Append(self.menu.foo, "&Foo")
self.menu.foo.bar_A = self.menu.foo.Append(wx.ID_ANY, "Bar&A\tShift+A")
self.menu.foo.bar_B = self.menu.foo.Append(wx.ID_ANY, "Bar&B\tShift+B")
self.Bind(wx.EVT_MENU, self.handle_A, self.menu.foo.bar_A)
self.Bind(wx.EVT_MENU, self.handle_B, self.menu.foo.bar_B)
def init_text(self):
self.box = wx.BoxSizer(wx.HORIZONTAL)
self.SetSizer(self.box)
self.text_A = wx.TextCtrl(self, style=wx.TE_MULTILINE)
self.text_B = wx.TextCtrl(self, style=wx.TE_MULTILINE)
self.box.Add(self.text_A, 1, flag=wx.EXPAND)
self.box.Add(self.text_B, 1, flag=wx.EXPAND)
def handle_A(self, event):
print('A')
def handle_B(self, event):
print('B')
app = wx.App()
Foo()
app.MainLoop()
用类似 self.text_A.Bind(wx.EVT_MENU, self.handle_A, self.menu.foo.bar_A)
的方式绑定菜单事件完全不管用。
我应该使用 wx.EVT_KILL_FOCUS
和 wx.EVT_SET_FOCUS
来绑定/解绑菜单项,设置/重置快捷键,以及启用/禁用菜单项吗?这听起来对于较大的应用程序来说有点复杂,通常我想知道 wxPython 应用程序限制菜单快捷键作用范围并动态启用/禁用菜单项的正确(最常用、干净整洁)方法是什么。
谢谢!
1 个回答
我几年前写了一篇关于菜单的文章,地址在这里:http://www.blog.pythonlibrary.org/2008/07/02/wxpython-working-with-menus-toolbars-and-accelerators/
文章里讲了如何禁用菜单。wxPython的演示包里也有一个相关的例子。不过,我觉得你得把菜单事件绑定到框架对象上,直接绑定到文本控件上可能不太行。我认为在处理焦点事件时做启用或禁用的操作会更合适。
如果想要解除绑定某个事件,可以用UnBind方法。想了解更多信息,可以查看这两个链接:http://zetcode.com/wxpython/events/ 或 http://www.wxpython.org/docs/api/wx.EvtHandler-class.html。