subclassing wxMenuBar...

Tom Jenkins tjenkins at
Tue Jun 5 15:27:57 CEST 2001

Tom Jenkins <tjenkins at> wrote in message news:<mailman.991661708.12433.python-list at>...
> Bjorn Pettersen wrote:
> > I was stepping through the wxPython tutorial, and came across the part
> > where they're creating the menus. It seemed like a good idea to put the
> > menu definition in a datafile instead of specifying it programatically,
> > so I though it would be a good chance to get some xml experience too...
> > 
> Well I wouldn't subclass wxMenuBar; instead I'd create a helper class 
> that would handle reading the xml and loading it into the wxMenuBar.  I 
> took your code and changed it to work as a helper.  Along the way I 
> added some functionality.

Err... well it looks like the mailing list -> newsgroup bridge
stripped out the attachment that contained the code for the helper
class.  So let me follow up by putting it directly in the message

XMLMenuLoader: Class to handle loading a wxMenuBar with menu items
defined in XML

author: Tom Jenkins <tjenkins at>
based on code by Bjorn Pettersen <BPettersen at>

#*TODO*: refactor load into base class that handles loading the menu
in another way so we can have ListMenuLoader, StreamMenuLoader, etc...


from xml.dom import minidom
from wxPython.wx import *
def filterText(nodelist):
   return [ x for x in nodelist if x.nodeType != x.TEXT_NODE ]
class XMLMenuLoader:
   def __init__(self, filename, wxMenuBar = None):
		'''Save the filename and menubar to use'''
		self._filename = filename
   def setMenuBar(self, wxMenuBar = None):
		''' set the menubar property to the given menubar
		wxMenuBar -> the root menubar of the frame'''
		self._wxMenuBar = wxMenuBar
   def menuBar(self):
		'''Return the stored menubar'''
		return self._wxMenuBar
   def load(self, wxMenuBar = None, controller = None):
		'''Load the menubar with the menu items stored in XML format in
                   the instance's filename property
		wxMenuBar -> the root menubar of the frame; if given will become
                the instances new menubar property
		controller -> the class instance that will receive any callbacks
                stored in the menu items' callback attribute
		if wxMenuBar != None:
		menubar = minidom.parse(self._filename)
		# loop over and process all of the menu elements in the menubar
		for menu in menubar.getElementsByTagName('menu'):
			menuName = menu.attributes['name'].nodeValue.replace('_', '&')
			wxmenu = wxMenu()
			for menuItem in filterText(menu.childNodes):
				if menuItem.tagName == 'menuitem':
						attrs = menuItem.attributes
						idTag = int( attrs['id'].nodeValue )
						name = attrs['name'].nodeValue.replace('_', '&')
						info = attrs['info'].nodeValue
						wxmenu.Append(idTag, name, info)
				# only load the callbacks if there is a controller
				if controller:
						callback = attrs['callback'].nodeValue
						handler = getattr(controller, callback, None)
						if handler:
							EVT_MENU(controller, idTag, handler)
					except KeyError, ex:
						# didn't have a callback attribute - skip
						#*TODO*: check if there is a better way; maybe a has_key test?
				elif menuItem.tagName == 'separator':
			self.menuBar().Append(wxmenu, menuName)

> Thanks for the initial post Bjorn, I had fun working on this...

Didn't-have-fun-getting-the-code-out-to-you-though-ly, yours

More information about the Python-list mailing list