【问题标题】:wxPython: how to disable all accelerators temporarily?wxPython:如何暂时禁用所有加速器?
【发布时间】:2009-09-16 14:56:16
【问题描述】:

如何临时禁用 wxPython 应用程序中的所有加速器?

例如,我有一个特殊的 TextCtrl,我想用它来记录单个按键,并且我不希望该按键被视为加速键。虽然该小部件具有焦点,但我想禁用所有加速器。

在 wxPython 邮件列表中,建议我将 EVT_UPDATE_UI 绑定到所有菜单 ID,并根据小部件关注的内容启用或禁用事件。这意味着我必须知道我所有的菜单 ID,但我不知道。这适用于允许用户定义自己的菜单项和可能自己的加速器的应用程序。

【问题讨论】:

  • 您的目标是哪个操作系统?还是跨平台?
  • 跨平台,虽然我们绝大多数用户都在linux上

标签: wxpython


【解决方案1】:

如果您想禁用加速键,SetAcceleratorTable 确实有效 例如在这里我使用 SetAcceleratorTable 禁用加速键,禁用快捷键有点困难,我正在使用一种更改所有菜单文本的 hacky 方式,但顶部菜单仍然在 alt-m 上打开,但其余部分被禁用。

另外,我认为您可以捕获 EVT_CHAT/EVT_KEY_UP 框架及其子项并轻松阻止事件,但您需要小心。

import wx

class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, style=wx.DEFAULT_FRAME_STYLE|wx.WS_EX_PROCESS_UI_UPDATES,
                    parent=None,size=(400,300))
        self._setMenu()
        self.Show()
        self._menuTextMap = {}
        self.btn = wx.Button(self, -1, "Disable Accel")
        self.btn.Bind(wx.EVT_BUTTON, self._toggleAccel)

    def _enableMenuShortcuts(self, enable):
        if enable and not self._menuTextMap:
            return

        def enableMenu(menuItem, i=-1):
            if i==-1:#item
                text = menuItem.GetText()
            else:#menu
                text = self.menuBar.GetLabelTop(i)

            if enable:
                print text,
                newText = self._menuTextMap[text]
                print newText
            else:
                newText = text.replace('&','')+" disabled"
                self._menuTextMap[newText] = text

            if i:
                menuItem.SetText(newText)
            else:
                self.menuBar.SetLabelTop(i,newText)

        for i in range(self.menuBar.GetMenuCount()):
            menu = self.menuBar.GetMenu(i)
            enableMenu(menu, i)
            for menuItem in menu.GetMenuItems():
                enableMenu(menuItem)

    def _toggleAccel(self, event):
        self.accelOn = not self.accelOn
        if self.accelOn:
            self.SetAcceleratorTable(self.aTable)
            self._enableMenuShortcuts(True)
            self.btn.SetLabel("Disable Accel")
        else:
            self.SetAcceleratorTable(wx.NullAcceleratorTable)
            self._enableMenuShortcuts(False)
            self.btn.SetLabel("Enable Accel")
        #self.menuBar.SetAcceleratorTable(wx.NullAcceleratorTable)

    def _setMenu(self):
        self.menuBar = wx.MenuBar()

        myMenu= wx.Menu()
        accelList = []

        for i in range(9):
            ID = wx.NewId()
            myMenu.Append(ID, "Item &%s"%(i+1))
            wx.EVT_MENU(self, ID, self._onMenu)
            accelList.append((wx.ACCEL_CTRL, ord('A')+i, ID))

        self.menuBar.Append(myMenu, "&My Menu")
        self.SetMenuBar( self.menuBar)
        self.accelOn=True
        self.aTable = wx.AcceleratorTable(accelList)
        self.SetAcceleratorTable(self.aTable);

    def  _onMenu(self, event):
        item = self.menuBar.GetMenu(0).FindItemById(event.GetId())
        wx.MessageBox("Menu -> %s"%(item.GetItemLabel(),))

app = wx.PySimpleApp()
app.SetTopWindow(MainFrame())
app.MainLoop()

你说EVT_UPADTE_UI 如果你知道所有的 id 可能会工作,因为你可以循环遍历所有菜单项

for i in range(self.menuBar.GetMenuCount()):
    menu = self.menuBar.GetMenu(i)
    enableMenu(menu, i)
    for menuItem in menu.GetMenuItems():
        enableMenu(menuItem)

【讨论】:

    【解决方案2】:

    要禁用加速器,您可以将加速器表设置为预定义的 wx.NullAcceleratorTable

    ctrl.SetAcceleratorTable(wx.NullAcceleratorTable)
    

    我这样做是为了在帧中永久禁用加速器表,我假设如果你想暂时这样做,你可以根据需要交换表。

    【讨论】:

    • 那行不通。我尝试为控件、控件所在的面板、面板所在的框架以及作为框架一部分的菜单栏设置一个空加速器表。在所有情况下,绑定到菜单栏的加速器都会触发。
    • 我明白了,我的错...我错过了您问题中所述的菜单问题,并且 NullAcceleratorTable 不会更改菜单快捷方式。
    猜你喜欢
    • 1970-01-01
    • 2012-07-23
    • 2011-07-03
    • 1970-01-01
    • 2021-08-14
    • 2015-02-24
    • 2011-06-13
    相关资源
    最近更新 更多