I have created a custom class that my windows can use for popup menus. Usage is
as follows: the window constructs a PopupMenu object, passing its constructor a
recursive list of simple MenuItem objects (not wx.MenuItems) that represent the
attributes and bindings of each menu item (text, is_checkable, etc...). The
PopupMenu class constructor also gets a reference to the window, so it can do
the event binding as well as the menu creation.
I have implemented and tested the event binding in the PopupMenu class two
different ways, and I'm looking for advice on which is best.
0. Each MenuItem gets a dynamically acquired id from wx.NewId() that is used for
the life of that popup menu. Menu events are bound using this id and the window
reference. Because this all happens in the PopupMenu constructor, the window
doesn't have to know anything about menu ids.
1. The MenuItems get assigned static ids by the window before passing to the
PopupMenu constructor. Menu events are bound using these ids the first time the
popup menu is created. Since the ids are constants, each subsequent time the
same popup menu is created, the events do not need to be bound.
It seems to me that the negative performance impact of binding each time the
popup is created would be minimal, and that the benefit gained from
encapsulating all menu-related stuff in the PopupMenu class outweighs this. The
possible downside to 0. is that I don't know how to unbind events each time the
popup menu is destroyed so that I don't get a leak in the window's event handler
table.
Usage is like the following:
def OnContextMenu(self, event):
...
popup = PopupMenu(self, menu_item_list)
self.PopupMenu(popup)
The PopUpMenu constructor does the binding. wx.Window.PopupMenu draws the menu
and doesn't return until the user has dismissed it. Can I define a destructor
__del__ for PopupMenu and do the unbinding in there? To prevent the event
handler table from growing, would it be sufficient to do this and then
explicitly call
del popup
afterwards?
Thoughts?
Thanks,
Tim
Hello,
Please help me with a couple of related questions:
- Aren't event handlers unbound automatically when a window is destroyed?
- If yes, is there a difference for handlers bound to the event source window:
window.Bind(event, func)
and handlers bound to some parent window or frame:
ParentWindow.Bind(event, func, window)?
···
--
Thanks,
Olga Marchevska
-------- Original Message --------
Subject: Re:[wxpython-users] dynamic vs. static event binding in a custom popup menu class
From: Robin Dunn <robin@alldunn.com>
To: wxpython-users@lists.wxwidgets.org
Date: Fri Apr 04 2008 02:40:20 GMT+0400
Tim Black wrote:
It seems to me that the negative performance impact of binding each time the
popup is created would be minimal, and that the benefit gained from
encapsulating all menu-related stuff in the PopupMenu class outweighs this. The
possible downside to 0. is that I don't know how to unbind events each time the
popup menu is destroyed so that I don't get a leak in the window's event handler
table.
There is an Unbind method that takes the same parameters as the Bind method except you don't pass the handler function. Or you can just use Bind and pass None for the handler function.
Robin,
Thanks for explanation.
It seems, that explicit Unbind() for temporarily created controls is more safe (to avoid events from already dead windows).
···
--
Olga Marchevska
-------- Original Message --------
Subject: Re:[wxpython-users] dynamic vs. static event binding in a custom popup menu class
From: Robin Dunn <robin@alldunn.com>
To: wxpython-users@lists.wxwidgets.org
Date: Mon Apr 07 2008 21:14:21 GMT+0400
Olga Marchevska wrote:
Hello,
Please help me with a couple of related questions:
- Aren't event handlers unbound automatically when a window is destroyed?
Yes.
- If yes, is there a difference for handlers bound to the event source window: window.Bind(event, func)
and handlers bound to some parent window or frame:
ParentWindow.Bind(event, func, window)?
Yes. If window is destroyed before ParentWindow is destroyed, then in the later case ParentWindow will still have event bindings for events coming from window. (Which won't ever happen unless some other child window is created with the same ID.)