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):
1 # pyxboil.py
2 #
3 # This script generates boilerplate classes out of an XRC resource file.
4 # For each top-level windows (Panel, Frame or Dialog) a class is generated
5 # and all the controls become attributes of the class.
6
7 import sys
8 import re
9 import os
10 from xml.dom import minidom
11
12 # --------------------------- Template definitions --------------------------
13 fileHeaderTemplate = """\
14 # This file has been automatically generated by PyXBoil.
15 # Please do not edit it manually.
16
17 import wx
18 from wx.xrc import *
19 """
20
21 classDeclarationTemplate = """\
22 class %(windowName)sBase(wx.%(windowClass)s):
23 def OnInit(self):
24 \"\"\" This function is called during the class's initialization.
25
26 Override it for custom setup (setting additional styles, etc.)\"\"\"
27 pass
28
29 def __init__(self, parent, res):
30 \"\"\" Pass an initialized wx.xrc.XmlResource into res \"\"\"
31
32 # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
33 pre = wx.Pre%(windowClass)s()
34 res.LoadOnPanel(pre, parent, "%(windowName)s")
35 self.OnInit()
36 self.PostCreate(pre)
37
38 # Define variables for the controls"""
39
40 controlDeclationTemplate = """\
41 self.%(controlName)s = XRCCTRL(self, \"%(controlName)s\")"""
42
43 # ------------------------- GeneratePythonForXRC ----------------------------
44 def GeneratePython(xrcFile, outFile):
45 xmldoc = minidom.parse(xrcFile)
46 resource = xmldoc.childNodes[0]
47 topWindows = [e for e in resource.childNodes
48 if e.nodeType == e.ELEMENT_NODE and e.tagName == "object"]
49 print >> outFile, fileHeaderTemplate
50
51 # Generate a class for each top-window object (Frame, Panel, Dialog, etc.)
52 for topWindow in topWindows:
53 eventFunctions = [] # a list to store the code for the event functions
54 windowClass = topWindow.getAttribute("class")
55 windowClass = re.sub("^wx", "", windowClass)
56 windowName = topWindow.getAttribute("name")
57 print >> outFile, classDeclarationTemplate % locals()
58
59 # Generate a variable for each control, and standard event handlers
60 # for standard controls.
61 for control in topWindow.getElementsByTagName("object"):
62 controlClass = control.getAttribute("class")
63 controlClass = re.sub("^wx", "", controlClass)
64 controlName = control.getAttribute("name")
65 if controlName != "" and controlClass != "":
66 print >> outFile, controlDeclationTemplate% locals()
67
68 print >> outFile
69 print >> outFile, "\n".join(eventFunctions)
70
71 # --------------------- Main ----------------
72
73 def Usage():
74 print """
75 xrcpy -- Python boilerplate code generator for XRC resources.
76
77 Usage : python pyxrc.py <resource.xrc>
78
79 The Python code is printed to the standard output.
80 """
81
82 def main():
83 if len(sys.argv) != 2:
84 Usage()
85 else:
86 inFilename = sys.argv[1]
87 outFilename = os.path.splitext(inFilename)[0] + "_xrc.py"
88
89 try:
90 inStream = file(inFilename)
91 try:
92 outStream = file(outFilename, "w")
93 except IOError:
94 print >> sys.stderr, "Can't open '%s'!" % outFilename
95 else:
96 GeneratePython(inStream, outStream)
97 print "Result stored in %s." % outFilename
98 except IOError:
99 print >> sys.stderr, "Can't open '%s'!" % inFilename
100
101
102 if __name__ == "__main__":
103 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
1 import sys
2 import wx
3 from wx.xrc import *
4 from pyxboil_demo_xrc import *
5
6 XML_RESOURCE_FILE = "pyxboil_demo.xrc"
7
8 class MyFrame(wx.Frame):
9 def __init__(self, parent=None):
10 wx.Frame.__init__(self, parent)
11
12 class MyPanel(MyPanelBase):
13 def __init__(self, parent, res):
14 MyPanelBase.__init__(self, parent, res)
15 self.Bind(wx.EVT_BUTTON, self.OnOk, self.OkButton)
16
17 def OnOk(self, e):
18 message = "You are " + self.firstName.GetValue() + " " + self.lastName.GetValue() + "!"
19 dlg = wx.MessageDialog(self, message, "Hmm...", wx.OK | wx.ICON_INFORMATION)
20 dlg.ShowModal()
21 dlg.Destroy()
22
23 class MyApp(wx.App):
24 def OnInit(self):
25 self.res = XmlResource(XML_RESOURCE_FILE)
26 self.frame = MyFrame(None)
27 self.panel = MyPanel(self.frame, self.res)
28 self.frame.Center()
29 self.frame.Show(1)
30 return True
31
32 if __name__ == '__main__':
33 app = MyApp()
34 app.MainLoop()
pyxboil_demo.xrc
<?xml version="1.0" encoding="cp1255"?>
<resource>
<object class="wxPanel" name="MyPanel">
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxStaticText">
<label>So, who are you?</label>
<font>
<size>12</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
</object>
<flag>wxALL</flag>
<border>5</border>
</object>
<object class="spacer">
<size>0,15</size>
</object>
<object class="sizeritem">
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<object class="wxStaticText">
<label>First Name:</label>
<size>80,20</size>
</object>
</object>
<object class="spacer">
<size>5,0</size>
</object>
<object class="sizeritem">
<object class="wxTextCtrl" name="firstName"/>
<option>1</option>
<flag>wxEXPAND</flag>
</object>
</object>
<flag>wxALL|wxEXPAND</flag>
<border>5</border>
</object>
<object class="sizeritem">
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<object class="wxStaticText">
<label>Last Name:</label>
<size>80,20</size>
</object>
</object>
<object class="spacer">
<size>5,0</size>
</object>
<object class="sizeritem">
<object class="wxTextCtrl" name="lastName"/>
<option>1</option>
<flag>wxEXPAND</flag>
</object>
</object>
<flag>wxALL|wxEXPAND</flag>
<border>5</border>
</object>
<object class="spacer">
<option>1</option>
</object>
<object class="sizeritem">
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="spacer">
<size>0,0</size>
<option>1</option>
</object>
<object class="sizeritem">
<object class="wxButton" name="OkButton">
<label>OK</label>
<style>wxSUNKEN_BORDER</style>
</object>
</object>
<object class="spacer">
<size>5,0</size>
</object>
</object>
<flag>wxEXPAND</flag>
</object>
<object class="spacer">
<size>0,10</size>
</object>
</object>
<size>350,100</size>
</object>
</resource>
pyxboil_demo_xrc.py
This is the file that is generated automatically by pyxboil for the pyxboil_demo.xrc XRC file.
1 # This file has been automatically generated by PyXBoil.
2 # Please do not edit it manually.
3
4 import wx
5 from wx.xrc import *
6
7 class MyPanelBase(wx.Panel):
8 def OnInit(self):
9 """ This function is called during the class's initialization.
10
11 Override it for custom setup (setting additional styles, etc.)"""
12 pass
13
14 def __init__(self, parent, res):
15 """ Pass an initialized wx.xrc.XmlResource into res """
16
17 # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
18 pre = wx.PrePanel()
19 res.LoadOnPanel(pre, parent, "MyPanel")
20 self.OnInit()
21 self.PostCreate(pre)
22
23 # Define variables for the controls
24 self.firstName = XRCCTRL(self, "firstName")
25 self.lastName = XRCCTRL(self, "lastName")
26 self.OkButton = XRCCTRL(self, "OkButton")
