[snip]
Thanks, that helps me understand. I didn't even know about
EVT_UPDATE_UI, so now I've read up on the docs and list archives for
it.
Patrick, could you do this in place of the repeated calls with each ID?
wx.EVENT_UPDATE_UI(self, -1, self.onUpdateMenu)
Also, in the event handler, I would love to see if the menu item has a
callback attribute and then simply invoke it. But AFAICT from both docs
and source, an UpdateUIEvent() doesn't have a pointer back to the menu
item, only it's integer ID!
Sidebar rant: Why does wxWindows insist on passing ints all over the
place, instead of just using...(drum roll)...objects!!! Grrr...
Hmmm, maybe in my menu.add() mixin method, I could maintain a dictionary
mapping ints to menu items. Then my single handler becomes:
def onUpdateMenu(self, event):
menuItem = self._menuItemForStupidInt[event.int]
updateUI = getattr(menuItem, 'updateUI', None)
if updateUI:
updateUI(event, menuItem)
So now the set up for a single menu item would be:
menu.add('Revert buffer', callback=self.revertBuffer,
updateUI=self.updateRevertBuffer)
def updateRevertBuffer(self, event, item):
event.enable(hasattr(self, 'bufferRevert') and self.hasBuffer())
Another variation would be to let the add() method figure out the
methods based on the "name":
menu.add('Revert buffer', owner=self, name='revertBuffer')
Finally, another thought is that the add() mixin could bind the
EVT_UPDATE_UI() which would eliminate the need to map the ints to the
menu items.
Feedback appreciated. I'll try something like this some time soon.
In case you're wondering where menu.add() comes from, I'm currently use
it and have it defined as this:
from wxPython import wx
def add(self, title, helpStr='', itemKind=wx.ITEM_NORMAL, callback=None,
id=None):
"""
Example:
menu.add("&About", "Information about this program",
callback=self.onAbout)
Adds a new menu item with the given parameters, including the event
hookup and callback,
and returns the new menu item.
Normally you will not pass the 'id'.
"""
if id is None:
id = wx.NewId()
item = wx.MenuItem(self, id, title, helpStr, itemKind)
self.appendItem(item)
if callback:
receiver = getattr(callback, 'im_self', self) # im_self is the
target of a BoundMethod
receiver.forEvent('menu', id, callback)
return item
from wxPython.wx import MenuPtr as Menu
assert not hasattr(Menu, 'add'), Menu.add
Menu.add = add
···
On Friday 25 April 2003 05:50 pm, Patrick K. O'Brien wrote:
Chuck Esterbrook <ChuckEsterbrook@yahoo.com> writes:
> Hi,
>
> What do folks use to keep there pulldown menu item enable/disable
> states correct while an app is being used?
>
> Obviously, I could make sure that at every step of my code I'm
> invoking Enable() on the right items with the right value. I fear
> that will be complicated.
This is not a particularly elegant way to do it, but for now I'm
using the following in PyCrust/PyAlaMode/etc. (All my Py* programs
inherit from the same base frame class, defined in frame.py.)
I've got a frame that creates a menu. For each menu item, I
associate the same Update UI event handler, like this:
wx.EVT_UPDATE_UI(self, ID_NEW, self.OnUpdateMenu)
wx.EVT_UPDATE_UI(self, ID_OPEN, self.OnUpdateMenu)
wx.EVT_UPDATE_UI(self, ID_REVERT, self.OnUpdateMenu)
wx.EVT_UPDATE_UI(self, ID_CLOSE, self.OnUpdateMenu)
wx.EVT_UPDATE_UI(self, ID_SAVE, self.OnUpdateMenu)
wx.EVT_UPDATE_UI(self, ID_SAVEAS, self.OnUpdateMenu)
...
The handler is coded as this:
def OnUpdateMenu(self, event):
"""Update menu items based on current status and context."""
win = wx.wxWindow_FindFocus()
id = event.GetId()
event.Enable(True)
try:
if id == ID_NEW:
event.Enable(hasattr(self, 'bufferNew'))
elif id == ID_OPEN:
event.Enable(hasattr(self, 'bufferOpen'))
--
Chuck
http://ChuckEsterbrook.com