1
votes

wxPython accelerators seem to fire even when their associated menu items are disabled. Is this a bug? Shouldn't the accelerator keys NOT fire in these situations?

In the short stand-alone example below, if you right click, a popup menu appears with a single menuitem which is DISABLED. The associated accelerator key CMD S can still be triggered, however!?

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()

Perhaps I need to explicitly check in each handler function, whether the ‘menuitem that triggered it’ is enabled or disabled. This sounds a bit tedious - things should ideally be automatic. Interestingly, this post talks about how these things can indeed be automatic (albiet not wxpython related, and seems specific to windows).

If an accelerator has the same identifier as a menu item and the menu item is grayed or disabled, the accelerator is disabled and does not generate a WM_COMMAND or WM_SYSCOMMAND message.

I am running Mac OSX under Python 3.7 and wxPython 4.04.

1

1 Answers

0
votes

I think that you may be correct.
You may have to check or rebuild the accelerator table each time.
You can disable all Accelerators temporarily with:

self.SetAcceleratorTable(wx.NullAcceleratorTable)