Reputation: 59333
I have an application that allows some controllers to change the layout of the main menu bar. I do this by passing the main menu bar to the controller, then the controller adds some menus to it. My issue is binding menu click events to those added menus. It's very easy in theory:
def bind_main_menu_bar(self, main_menu_bar):
self.main_menu_bar = main_menu_bar
edit_menu = shared.create_menu([
(const.ID_UNDO, self.LABEL_UNDO_EMPTY),
(const.ID_REDO, self.LABEL_REDO_EMPTY),
(),
(const.ID_VALIDATE_ADDRESSES, 'Validate selected addresses'),
(const.ID_VALIDATE_ALL_ADDRESSES, 'Validate all addresses'),
])
edit_menu.Bind(wx.EVT_MENU, self.on_menu)
edit_menu.Bind(wx.EVT_UPDATE_UI, self.on_menu_update)
main_menu_bar.Insert(1, edit_menu, 'Edit')
This works excellently in OSX, but in Windows, only the wx.EVT_MENU
event works when binding the event directly to the edit_menu
menu. In other words, the wx.EVT_UPDATE_UI
event handler is never triggered. I've also tried binding EVT_MENU_OPEN
, EVT_MENU_CLOSE
and EVT_MENU_HIGHLIGHT
but none of them work. They all work when I bind them to the top level frame, but then there is no way to limit the event handler to only the edit_menu
menu.
Is this a bug, or is there something I'm overlooking? Also, can anybody spot a workaround to my issue?
I'm using wxPython 2.9 (dev) on Window 8.
Upvotes: 0
Views: 653
Reputation: 56
Mike's right, avoid explicit IDs -- and you don't need them (see the wxPython Style guide in the wiki for details).
Menu items are not regular Windows, so you can't do the normal event binding thing with them -- too bad.
However, when you bind the event to the frame, you can specify where the event comes from. My usual idiom for binding menu events:
FileMenu = wx.Menu()
item = FileMenu.Append(wx.ID_EXIT, "&Quit")
self.Bind(wx.EVT_MENU, self.OnQuit, item)
In this case, self
is a Frame
- so you are saying: bind the EVT_MENU
to the frame, call the self.OnQuit
as a the callback, but only bind events from this particular menu item.
This is uglier when you are doing dynamic binding, but it should work.
Note that in this example I'm using an ID - the exception to that rule is that using standard IDs (like wx.ID-EXIT
, wx.ID_HELP
) is nice, because then wx
can "do the right thing" on various platforms (like more the quite menu to the app menu on OS-X).
Upvotes: 4
Reputation: 33071
I'm pretty sure that you're supposed to bind menu events to the frame, not the menu items themselves. Try that and see if it works.
Upvotes: 1