5 #---------------------------------------------------------------------- 
   7 resourceText 
= r
'''<?xml version="1.0"?> 
  10 <!-- Notice that the class is NOT a standard wx class --> 
  12 <object class="MyCustomPanel" name="MyPanel"> 
  14     <object class="wxStaticText" name="label1"> 
  15         <label>This panel is a custom class derived from wx.Panel,\nand is loaded by a custom XmlResourceHandler.</label> 
  22 #---------------------------------------------------------------------- 
  24 class MyCustomPanel(wx
.Panel
): 
  25     def __init__(self
, parent
, id, pos
, size
, style
, name
): 
  26         wx
.Panel
.__init
__(self
, parent
, id, pos
, size
, style
, name
) 
  28         # This is the little bit of customization that we do for this 
  30         self
.Bind(wx
.EVT_SIZE
, self
.OnSize
) 
  31         t 
= wx
.StaticText(self
, -1, "MyCustomPanel") 
  34         f
.SetPointSize(f
.GetPointSize()+2) 
  38     def OnSize(self
, evt
): 
  40         w
, h 
= self
.t
.GetTextExtent(self
.t
.GetLabel()) 
  41         self
.t
.SetPosition(((sz
.width
-w
)/2, (sz
.height
-h
)/2)) 
  44 # To do it the more complex way, (see below) we need to write the 
  45 # class a little differently...  This could obviously be done with a 
  46 # single class, but I wanted to make separate ones to make clear what 
  47 # the different requirements are. 
  48 class PreMyCustomPanel(wx
.Panel
): 
  53     def Create(self
, parent
, id, pos
, size
, style
, name
): 
  54         wx
.Panel
.Create(self
, parent
, id, pos
, size
, style
, name
) 
  55         self
.Bind(wx
.EVT_SIZE
, self
.OnSize
) 
  56         t 
= wx
.StaticText(self
, -1, "MyCustomPanel") 
  59         f
.SetPointSize(f
.GetPointSize()+2) 
  63     def OnSize(self
, evt
): 
  65         w
, h 
= self
.t
.GetTextExtent(self
.t
.GetLabel()) 
  66         self
.t
.SetPosition(((sz
.width
-w
)/2, (sz
.height
-h
)/2)) 
  68 #---------------------------------------------------------------------- 
  70 class MyCustomPanelXmlHandler(xrc
.XmlResourceHandler
): 
  72         xrc
.XmlResourceHandler
.__init
__(self
) 
  73         # Specify the styles recognized by objects of this type 
  74         self
.AddStyle("wx.NO_3D", wx
.NO_3D
); 
  75         self
.AddStyle("wx.TAB_TRAVERSAL", wx
.TAB_TRAVERSAL
); 
  76         self
.AddStyle("wx.WS_EX_VALIDATE_RECURSIVELY", wx
.WS_EX_VALIDATE_RECURSIVELY
); 
  77         self
.AddStyle("wx.CLIP_CHILDREN", wx
.CLIP_CHILDREN
); 
  78         self
.AddWindowStyles(); 
  80     # This method and the next one are required for XmlResourceHandlers 
  81     def CanHandle(self
, node
): 
  82         return self
.IsOfClass(node
, "MyCustomPanel") 
  84     def DoCreateResource(self
): 
  85         # NOTE: wxWindows can be created in either a single-phase or 
  86         # in a two-phase way.  Single phase is what you normally do, 
  87         # and two-phase creates the instnace first, and then later 
  88         # creates the actual window when the Create method is called. 
  89         # (In wxPython the first phase is done using the wxPre* 
  90         # function, for example, wxPreFrame, wxPrePanel, etc.) 
  92         # wxXmlResource supports either method, a premade instance can 
  93         # be created and populated by xrc using the appropriate 
  94         # LoadOn* method (such as LoadOnPanel) or xrc can create the 
  95         # instance too, using the Load* method.  However this makes 
  96         # the handlers a bit more complex.  If you can be sure that a 
  97         # particular class will never be loaded using a pre-existing 
  98         # instance, then you can make the handle much simpler.  I'll 
  99         # show both methods below. 
 102             # The simple method assumes that there is no existing 
 103             # instance.  Be sure of that with an assert. 
 104             assert self
.GetInstance() is None 
 106             # Now create the object 
 107             panel 
= MyCustomPanel(self
.GetParentAsWindow(), 
 111                                   self
.GetStyle("style", wx
.TAB_TRAVERSAL
), 
 115             # When using the more complex (but more flexible) method 
 116             # the instance may already have been created, check for it 
 117             panel 
= self
.GetInstance() 
 119                 # if not, then create the instance (but not the window) 
 120                 panel 
= PreMyCustomPanel() 
 122             # Now call the panel's Create method to actually create the window 
 123             panel
.Create(self
.GetParentAsWindow(), 
 127                          self
.GetStyle("style", wx
.TAB_TRAVERSAL
), 
 131         # These two things should be done in either case: 
 132         # Set standard window attributes 
 133         self
.SetupWindow(panel
) 
 134         # Create any child windows of this node 
 135         self
.CreateChildren(panel
) 
 140 #---------------------------------------------------------------------- 
 143 class TestPanel(wx
.Panel
): 
 144     def __init__(self
, parent
, log
): 
 146         wx
.Panel
.__init
__(self
, parent
, -1) 
 148         # make the components 
 149         label 
= wx
.StaticText(self
, -1, "The lower panel was built from this XML:") 
 150         label
.SetFont(wx
.Font(12, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
)) 
 152         text 
= wx
.TextCtrl(self
, -1, resourceText
, 
 153                           style
=wx
.TE_READONLY|wx
.TE_MULTILINE
) 
 154         text
.SetInsertionPoint(0) 
 156         line 
= wx
.StaticLine(self
, -1) 
 159         res 
= xrc
.EmptyXmlResource() 
 160         res
.InsertHandler(MyCustomPanelXmlHandler()) 
 161         res
.LoadFromString(resourceText
) 
 163         # Now create a panel from the resource data 
 164         panel 
= res
.LoadObject(self
, "MyPanel", "MyCustomPanel") 
 167         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 168         sizer
.Add(label
, 0, wx
.EXPAND|wx
.TOP|wx
.LEFT
, 5) 
 169         sizer
.Add(text
, 1, wx
.EXPAND|wx
.ALL
, 5) 
 170         sizer
.Add(line
, 0, wx
.EXPAND
) 
 171         sizer
.Add(panel
, 1, wx
.EXPAND|wx
.ALL
, 5) 
 174         self
.SetAutoLayout(True) 
 177 #---------------------------------------------------------------------- 
 179 def runTest(frame
, nb
, log
): 
 180     win 
= TestPanel(nb
, log
) 
 183 #---------------------------------------------------------------------- 
 187 overview 
= """<html><body> 
 188 <h2><center>wx.XmlResourceHandler</center></h2> 
 190 Deriving a class from wx.XmlResourceHandler allows you to specify your 
 191 own classes in XRC resources, and your handler class will then be used 
 192 to create instances of that class when the resource is loaded. 
 199 if __name__ 
== '__main__': 
 202     run
.main(['', os
.path
.basename(sys
.argv
[0])] + sys
.argv
[1:])