XRCed is a visual tool for editing an XML file conforming to the XRC format. Every operation performed in XRCed has direct correspondence to XML structure. So it is not really the usual point-and-click GUI builder, but don't let that scare you.
XRCed is distributed with wxPython.
See also: XRCed Wish List
Subclassing -- adding your own GUI controls
In the image above, you can see a lot of standard controls. I will not describe them because I did not have any problems figuring them out. But you can also position custom GUI controls (i.e. your own code) by "subclassing" (or deriving from) one of the standard controls. This is a little tricky so is described here:
- First add the base class control into the tree
- Right click on it and select "subclass"
- In the subclass text window, enter the entire class name, including the module. For example, if I want a class "foo" in the file "bar" I would enter "bar.foo"
Next open up an editor and create the module and the class. When creating the class, you must use TwoStageCreation. I was creating a graphics editor panel so, here is what I did:
class DrawPanel(wx.Panel): def __init__(self): # wx.Panel.__init__(self) # DO NOT INITIALIZE THE BASE CLASS # Do not use the base class in this constructor # Add these lines verbatim p = wx.PrePanel() # Call the function PreXXX where XXX is your wx base class self.PostCreate(p) self.Bind(wx.EVT_WINDOW_CREATE, self.OnCreate) # When the panel is really created, notify me so I can do my initialization def OnCreate(self, event): self.Unbind(wx.EVT_WINDOW_CREATE) # Do all of your normal initialization here
Custom controls and plugins
This section is outdated. Please see XRCed Refactoring Project for more info.
Here's an overview of the draft plugin implementation.
On startup, XRCed is looking for XRCEDPATH environment variable. If it is a colon-separated list of plugin directories, then it tries to import each directory as a Python package.
In the package there should be XML handlers needed to load custom controls, and XRCed interface classes. Handlers are registered with XRCed using register function from xxx module.
XML handlers can be also provided in a C++ shared library which is loaded using ctypes package. The library must provide an extern "C" function AddHandlers which is called to add handlers to the global XmlResource object.
XRCed interface classes are defined in the same way as classes in xxx.py and registered using custom function. For each custom control an item is added to the 'custom' submenu (visible only if a non-toplevel object is selected).
Example1: adding LEDNumberCtrl from gizmos
import wx import wx.xrc as xrc import wx.gizmos as gizmos # Resource handler class class LEDNumberCtrlXmlHandler(xrc.XmlResourceHandler): def __init__(self): xrc.XmlResourceHandler.__init__(self) # Standard styles self.AddWindowStyles() # Custom styles self.AddStyle('wxLED_ALIGN_LEFT', gizmos.LED_ALIGN_LEFT) self.AddStyle('wxLED_ALIGN_RIGHT', gizmos.LED_ALIGN_RIGHT) self.AddStyle('wxLED_ALIGN_CENTER', gizmos.LED_ALIGN_CENTER) self.AddStyle('wxLED_DRAW_FADED', gizmos.LED_DRAW_FADED) def CanHandle(self,node): return self.IsOfClass(node, 'LEDNumberCtrl') # Process XML parameters and create the object def DoCreateResource(self): assert self.GetInstance() is None w = gizmos.LEDNumberCtrl(self.GetParentAsWindow(), self.GetID(), self.GetPosition(), self.GetSize(), self.GetStyle()) w.SetValue(self.GetText('value')) self.SetupWindow(w) return w # XRCed interface module import xxx # XRCed interface class class xxxLEDNumberCtrl(xxx.xxxObject): allParams = ['pos', 'size', 'style', 'value'] winStyles = ['wxLED_ALIGN_LEFT', 'wxLED_ALIGN_RIGHT', 'wxLED_ALIGN_CENTER', 'wxLED_DRAW_FADED'] # Register XML handler xxx.register(LEDNumberCtrlXmlHandler) # Register XRCed interface class xxx.custom('LEDNumberCtrl', xxxLEDNumberCtrl)
__all__ = [ 'led' ]
Instead of making a plugin package, it is possible to use a special %comment directive directly in the resource file (comments can be added using pulldown menu in current XRCed version from CVS):
<?xml version="1.0" encoding="UTF-8"?> <resource> <!--%import led--> <object class="wxPanel" name="PANEL1"> <object class="LEDNumberCtrl"> <size>100,30</size> <value>12345</value> </object> <size>100,30</size> </object> </resource>
In this way the custom menu does not appear immediately, but after reloading the resource file.
The XRCed Tutorial page contains a walkthrough on using XRCed in a simple Python program.