## page was copied from Cookbook Template == Introduction == I am new to wxPython having just read Robin and Noel's excellent book "wxPython in action". In it they recommend creating menus from XML, so I came here and searched for the code but could find none. So I developed this code (as a newbie) which I am happy to share. I am sure it will benefit from re-factoring and expert comment. I have not tested it extensively but it seems to cope with the sample XML attached. == What Objects are Involved == The code is intended to be called from within your frame class __init__ method. You still have to manually set up all the handler methods within your frame class. == Process Overview == The XML is first read from file and the "&" (if any) converted to the "&" expected by the XML parser. This allows the XML to look more like menu code as used in the "generating menus from array example". The menu creator then reads the string data and interprets the various menu attributes to create the menu system. == Special Concerns == I am not sure I am raising the correct error classes or if there is sufficient error checking. == Code Sample == {{{ #!python #this section is the main routine code import wx import xml.sax.handler import sys def readXML(xmlfile): file=open(xmlfile,'r') fixedData= file.read() file.close() return fixedData.replace( "&", "&" ) def createMenus(self,menuData,frame): class MenuBuilder(xml.sax.handler.ContentHandler): def __init__(self): self.menuStack = [] self.text="" self.menu="" self.itemName="" self.type="" self.handler="" self.help="" self.helpStack={} self.item="" self.nameStack=[] def startElement(self, name, attrs): self.text="" if name=="menuItem": self.type="" self.help="" elif name=="menubar": menuBar=wx.MenuBar() self.menuStack.append((menuBar,"bar")) elif name=="menuName": self.menu="" elif name=="itemName": self.itemName="" elif name=="kind": self.type="" elif name=="handler": self.handler="" elif name=="help": self.help="" elif name=="menu": pass elif name=="separator": pass else: raise ValueError, "Invalid menu component %s" % name def endElement(self, name): if name=="menuItem": try: self.help=self.helpStack[self.itemName] del self.helpStack[self.itemName] except: self.help="" if self.type=="" or self.type=="normal": self.item=self.menuStack[-1][0].Append(id=wx.NewId(), text=self.itemName, help=self.help) elif self.type=="check": self.item=self.menuStack[-1][0].AppendCheckItem(id=wx.NewId(), text=self.itemName, help=self.help) elif self.type=="radio": self.item=self.menuStack[-1][0].AppendRadioItem(id=wx.NewId(), text=self.itemName, help=self.help) else: raise ValueError, "Unknown item type %s" % self.type frame.Bind(wx.EVT_MENU,self.handler,self.item) elif name=="menu": if self.menuStack[-2][1]=="bar": self.menuStack[-2][0].Append(menu=self.menuStack[-1][0],title=self.menuStack[-1][1]) else: try: self.help=self.helpStack[self.menuStack[-1][1]] del self.helpStack[self.menuStack[-1][1]] except: self.help="" self.menuStack[-2][0].AppendSubMenu(submenu=self.menuStack[-1][0],text=self.menuStack[-1][1],help=self.help) self.menuStack.pop() elif name=="separator": self.menuStack[-1][0].AppendSeparator() elif name=="menubar": frame.SetMenuBar(self.menuStack[-1][0]) elif name=="menuName": self.menu=wx.Menu() self.menuStack.append((self.menu,self.text)) self.nameStack.append(self.text) elif name=="itemName": self.itemName=self.text self.nameStack.append(self.text) elif name=="kind": self.type=self.text elif name=="handler": self.handler=getattr(frame,self.text) elif name=="help": self.help=self.text self.helpStack[self.nameStack[-1]]=self.help self.nameStack.pop() else: raise ValueError, "Invalid menu component %s" % name def characters(self, content): self.text+=content builder = MenuBuilder() xml.sax.parseString(menuData, builder) }}} This is the sample XML I used for testing {{{ &File File menu &Open OnOpen Open menu item &Save OnSave Save menu item &Close OnClose Close menu item E&xit OnExit Exit menu item &Edit Edit menu &Find OnFind File menu item &Replace OnReplace Replace menu item &Others Others menu &Others item 1 OnOthers1 Others menu item 1 &SubMenu Submenu Submenu item&1 OnSubmenu1 Submenu item 1 Submenu item&2 OnSubmenu2 Submenu item 2 Submenu item&3 OnSubmenu3 Submenu item 3 &Check/Radio Check and radio menu Check item 1 OnCheck1 Check item 1 check Check item 2 OnCheck2 Check item 2 check Check item 3 OnCheck3 Check item 3 check ` Radio item 1 OnRadio1 Radio item 1 radio Radio item 2 OnRadio2 Radio item 2 radio Radio item 3 OnRadio3 Radio item 3 radio }}} This is my app module {{{ #!python import wx import TestFrame2 import Library modules ={u'Library': [0, '', u'Library.py'], u'TestFrame2': [0, '', u'TestFrame2.py']} class TestApp(wx.App): def OnInit(self): self.main = TestFrame2.TestFrame(None) self.main.Show() self.SetTopWindow(self.main) return True def main(): application = TestApp(0) application.MainLoop() if __name__ == '__main__': main() }}} And this is my Testframe2 class (with trivial handlers) {{{ #!python import wx import Library class TestFrame(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, id=-1, name=u'TestFrame', parent = None, pos=wx.Point(480, 275), size=wx.Size(1280, 733), style=wx.DEFAULT_FRAME_STYLE, title=u'Menu testing program') self.SetClientSize(wx.Size(1280, 733)) self.CreateStatusBar() menuData=Library.readXML("menu.xml") Library.createMenus(self,menuData,self) def OnOpen(self,event): wx.MessageBox("You selected the open menu item") def OnSave(self,event): wx.MessageBox("You selected the save menu item") def OnClose(self,event): wx.MessageBox("You selected the close menu item") def OnExit(self,event): wx.MessageBox("You selected the exit menu item") self.Close() def OnFind(self,event): wx.MessageBox("You selected the find menu item") def OnReplace(self,event): wx.MessageBox("You selected the replace menu item") self.Close() def OnOthers1(self,event): wx.MessageBox("You selected the others1 menu item") def OnSubmenu1(self,event): wx.MessageBox("You selected the submenu item 1") def OnSubmenu2(self,event): wx.MessageBox("You selected the submenu item 2") def OnSubmenu3(self,event): wx.MessageBox("You selected the submenu item 3") def OnCheck1(self,event): wx.MessageBox("You checked item 1") def OnCheck2(self,event): wx.MessageBox("You checked item 2") def OnCheck3(self,event): wx.MessageBox("You checked item 3") def OnRadio1(self,event): wx.MessageBox("You selected radio item 1") def OnRadio2(self,event): wx.MessageBox("You selected radio item 2") def OnRadio3(self,event): wx.MessageBox("You selected radio item 3") }}} === Comments === I know I should be placing comments at the beginning of each module but I am not sure what level of detail is appropriate - so I chickened out and left them blank.