Ускорители wxpython запускаются даже при отключенном связанном пункте меню - PullRequest
0 голосов
/ 14 января 2019

Ускорители wxPython, похоже, работают даже тогда, когда связанные с ними пункты меню отключены. Это ошибка? Разве клавиши акселератора не должны срабатывать в таких ситуациях?

В приведенном ниже коротком автономном примере, если вы щелкнете правой кнопкой мыши, появится всплывающее меню с единственным пунктом меню, который ОТКЛЮЧЕН. Однако связанная клавиша ускорения CMD S все еще может быть активирована!?

import wx

help = """
If you right click on this window, a popup menu will appear with
a single menuitem which is DISABLED.

The associated accelerator key CMD S can still be triggered, however.

Is this a bug?
Shouldn't the accelerator keys NOT fire when its associated menu item
is disabled?
"""

class MyForm(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Accelerators fire even when menu item is disabled", size=(500,500))
        panel = wx.Panel(self, wx.ID_ANY)
        wx.StaticText(panel, wx.ID_ANY, help, wx.DefaultPosition, wx.DefaultSize, 0)
        self.popupmenu = wx.Menu()

        self.item: wx.Menuself.item = self.popupmenu.Append(wx.ID_ANY, "Do Something (CMD S)")
        self.Bind(wx.EVT_MENU, self.DoSomething, self.item)

        accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL,  ord('S'), self.item.GetId() )])
        self.SetAcceleratorTable(accel_tbl)

        self.item.Enable(False)  # hmm, accelerator still fires :-(

        self.Bind(wx.EVT_CONTEXT_MENU, self.OnRight)

    def OnRight(self, event):
        self.PopupMenu(self.popupmenu)

    def DoSomething(self, event):
        msg = f"Something is being triggered, even though menuitem enabled is {self.item.Enabled}"
        print(msg)
        dlg = wx.MessageDialog(self, msg, "Message", wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()


class MyApp(wx.App):
    def OnInit(self):
        frame = MyForm()
        frame.Show()
        self.SetTopWindow(frame)
        return True

# Run the program
if __name__ == "__main__":
    app = MyApp()
    app.MainLoop()

Возможно, мне нужно явно проверить в каждой функции-обработчике, включен ли «пункт меню, который его вызвал». Это звучит немного скучно - в идеале все должно быть автоматически. Интересно, что этот пост говорит о том, как эти вещи действительно могут быть автоматическими (albiet не относится к wxpython и, похоже, специфичны для окон).

Если ускоритель имеет тот же идентификатор, что и пункт меню и меню элемент недоступен, акселератор отключен и не создать сообщение WM_COMMAND или WM_SYSCOMMAND.

Я использую Mac OSX под Python 3.7 и wxPython 4.04.

1 Ответ

0 голосов
/ 14 января 2019

Я думаю, что вы можете быть правы.
Возможно, вам придется проверять или перестраивать таблицу акселераторов каждый раз.
Вы можете временно отключить все Accelerators с помощью:

self.SetAcceleratorTable(wx.NullAcceleratorTable)
...