wxPython: как временно отключить все ускорители?

Как временно отключить все ускорители в приложении wxPython?

Например, у меня есть специальный TextCtrl, который я хочу использовать для записи одного нажатия, и я не хочу, чтобы это нажатие обрабатывалось как ускоритель. Пока этот виджет имеет фокус, я хочу отключить все ускорители.

В списке рассылки wxPython было предложено привязать EVT_UPDATE_UI ко всем идентификаторам меню и включить или отключить событие в зависимости от того, на что сфокусирован виджет. Это означает, что я должен знать все свои идентификаторы меню, но я не знаю. Это для приложения, которое позволяет пользователям определять свои собственные пункты меню и, возможно, свои собственные ускорители.

16.09.2009 14:56:16
на какую ОС вы ориентируетесь? или это кроссплатформенный?
Anurag Uniyal 19.09.2009 03:54:03
кроссплатформенный, хотя подавляющее большинство наших пользователей используют Linux
Bryan Oakley 19.09.2009 11:38:28
2 ОТВЕТА
РЕШЕНИЕ

Если вы хотите отключить клавиши ускорения, SetAcceleratorTable работает, например, здесь я использую SetAcceleratorTable, чтобы отключить клавиши ускорения, отключить сочетания клавиш немного сложно, я использую хакерский способ изменения всех текстов меню, но верхнее меню все еще открывается на 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может работать, если вы знаете все идентификаторы, для этого вы можете просто пройти через все пункты меню

for i in range(self.menuBar.GetMenuCount()):
    menu = self.menuBar.GetMenu(i)
    enableMenu(menu, i)
    for menuItem in menu.GetMenuItems():
        enableMenu(menuItem)
0
19.09.2009 05:46:41

Чтобы отключить ускорители, вы можете установить в таблице ускорителей предопределенный wx.NullAcceleratorTable

ctrl.SetAcceleratorTable(wx.NullAcceleratorTable)

Я сделал это, чтобы навсегда отключить таблицу акселераторов в кадрах, и я предполагаю, что если вы хотите сделать это временно, вы можете просто поменять местами таблицы по мере необходимости.

-1
16.09.2009 19:59:29
Это не работает Я попытался установить нулевую таблицу ускорителей для элемента управления, для панели, в которой находится элемент управления, фрейма, в котором находится панель, и строки меню, являющейся частью фрейма. Во всех случаях, акселераторы, связанные с menubar, будут стрелять.
Bryan Oakley 16.09.2009 23:43:49
Я вижу, мой плохой ... Я пропустил проблему меню, изложенную в вашем вопросе, и NullAcceleratorTable не меняет ярлыки меню.
tom10 17.09.2009 03:32:26