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:])