== PyxBoil == The ''wxrc'' utility can create a C++ header with code that provides easy access to the controls defined in the XRC file. There was no such utility for wxPython that I could find, so I wrote one myself. It is in a very preliminary state, so don't expect too much. It works though. I've even patched XRCed a bit to automatically generate the relevant Python code each time you save the XRC. === pyxboil.py === This is the source of the tool (which can also be used somewhere else as a module): {{{ #!python # pyxboil.py # # This script generates boilerplate classes out of an XRC resource file. # For each top-level windows (Panel, Frame or Dialog) a class is generated # and all the controls become attributes of the class. import sys import re import os from xml.dom import minidom # --------------------------- Template definitions -------------------------- fileHeaderTemplate = """\ # This file has been automatically generated by PyXBoil. # Please do not edit it manually. import wx from wx.xrc import * """ classDeclarationTemplate = """\ class %(windowName)sBase(wx.%(windowClass)s): def OnInit(self): \"\"\" This function is called during the class's initialization. Override it for custom setup (setting additional styles, etc.)\"\"\" pass def __init__(self, parent, res): \"\"\" Pass an initialized wx.xrc.XmlResource into res \"\"\" # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.Pre%(windowClass)s() res.LoadOnPanel(pre, parent, "%(windowName)s") self.OnInit() self.PostCreate(pre) # Define variables for the controls""" controlDeclationTemplate = """\ self.%(controlName)s = XRCCTRL(self, \"%(controlName)s\")""" # ------------------------- GeneratePythonForXRC ---------------------------- def GeneratePython(xrcFile, outFile): xmldoc = minidom.parse(xrcFile) resource = xmldoc.childNodes[0] topWindows = [e for e in resource.childNodes if e.nodeType == e.ELEMENT_NODE and e.tagName == "object"] print >> outFile, fileHeaderTemplate # Generate a class for each top-window object (Frame, Panel, Dialog, etc.) for topWindow in topWindows: eventFunctions = [] # a list to store the code for the event functions windowClass = topWindow.getAttribute("class") windowClass = re.sub("^wx", "", windowClass) windowName = topWindow.getAttribute("name") print >> outFile, classDeclarationTemplate % locals() # Generate a variable for each control, and standard event handlers # for standard controls. for control in topWindow.getElementsByTagName("object"): controlClass = control.getAttribute("class") controlClass = re.sub("^wx", "", controlClass) controlName = control.getAttribute("name") if controlName != "" and controlClass != "": print >> outFile, controlDeclationTemplate% locals() print >> outFile print >> outFile, "\n".join(eventFunctions) # --------------------- Main ---------------- def Usage(): print """ xrcpy -- Python boilerplate code generator for XRC resources. Usage : python pyxrc.py The Python code is printed to the standard output. """ def main(): if len(sys.argv) != 2: Usage() else: inFilename = sys.argv[1] outFilename = os.path.splitext(inFilename)[0] + "_xrc.py" try: inStream = file(inFilename) try: outStream = file(outFilename, "w") except IOError: print >> sys.stderr, "Can't open '%s'!" % outFilename else: GeneratePython(inStream, outStream) print "Result stored in %s." % outFilename except IOError: print >> sys.stderr, "Can't open '%s'!" % inFilename if __name__ == "__main__": main() }}} === xrced_pyxboil.patch === This is a patch file for XRCed 0.1.7-1 so that when an resource.xrc is saved, a resource_xrc.py file is created. {{{ 383a384 > self.GeneratePython(path) 1155a1157,1170 > > def GeneratePython(self, xrcPath): > import pyxboil > import os.path > try: > pyPath = os.path.splitext(xrcPath)[0] + "_xrc.py" > infile = file(xrcPath) > outfile = file(pyPath, "w") > pyxboil.GeneratePython(infile, outfile) > except: > inf = sys.exc_info() > wxLogError(traceback.format_exception(inf[0], inf[1], None)[-1]) > wxLogError('Error writing file: %s' % pyPath) > raise }}} === Demo === This is simple application that uses pyxboil. You'll need to run ''python pyxboil.py pyxboil_demo.xrc'' to generate the boilerplate code in ''pyxboil_demo_xrc.py'' before you run ''pyxboil_demo.py''. ==== pyxboil_demo.py ==== {{{ #!python import sys import wx from wx.xrc import * from pyxboil_demo_xrc import * XML_RESOURCE_FILE = "pyxboil_demo.xrc" class MyFrame(wx.Frame): def __init__(self, parent=None): wx.Frame.__init__(self, parent) class MyPanel(MyPanelBase): def __init__(self, parent, res): MyPanelBase.__init__(self, parent, res) self.Bind(wx.EVT_BUTTON, self.OnOk, self.OkButton) def OnOk(self, e): message = "You are " + self.firstName.GetValue() + " " + self.lastName.GetValue() + "!" dlg = wx.MessageDialog(self, message, "Hmm...", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() class MyApp(wx.App): def OnInit(self): self.res = XmlResource(XML_RESOURCE_FILE) self.frame = MyFrame(None) self.panel = MyPanel(self.frame, self.res) self.frame.Center() self.frame.Show(1) return True if __name__ == '__main__': app = MyApp() app.MainLoop() }}} ==== pyxboil_demo.xrc ==== {{{ wxVERTICAL 12 default normal 0 wxALL 5 0,15 wxHORIZONTAL 80,20 5,0 wxEXPAND wxALL|wxEXPAND 5 wxHORIZONTAL 80,20 5,0 wxEXPAND wxALL|wxEXPAND 5 wxHORIZONTAL 0,0 5,0 wxEXPAND 0,10 350,100 }}} ==== pyxboil_demo_xrc.py ==== This is the file that is generated automatically by pyxboil for the pyxboil_demo.xrc XRC file. {{{ #!python # This file has been automatically generated by PyXBoil. # Please do not edit it manually. import wx from wx.xrc import * class MyPanelBase(wx.Panel): def OnInit(self): """ This function is called during the class's initialization. Override it for custom setup (setting additional styles, etc.)""" pass def __init__(self, parent, res): """ Pass an initialized wx.xrc.XmlResource into res """ # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "MyPanel") self.OnInit() self.PostCreate(pre) # Define variables for the controls self.firstName = XRCCTRL(self, "firstName") self.lastName = XRCCTRL(self, "lastName") self.OkButton = XRCCTRL(self, "OkButton") }}}