Introduction
Wizards are a familiar form of dialogs for Windows users. wxWizard is the wrapper for them that is included with wxPython.
This recipe offers an alternative to wxWizard which features visible internals and that may be easier to understand and modify.
What Objects are Involved
This recipe does not define a new wizard class. Rather wizards are based on instances of wxDialog, and each page or panel of a wizard is defined as a subclass of WizardPanel, which is just a subclass of wxPanel.
Process Overview
Define one subclass of WizardPanel for each panel (or page) in your wizard. The controls you need that are specific to one panel must have 'subpanel' of WizardPanel as their parent.
- At the point in your code where you need to display the wizard create an instance of wxDialog, instantiate the first panel of your wizard so that it is associated with the wxDialog instance and show the dialog.
- When you need to display a different panel in the wizard, perhaps in response to a 'next' button, destroy the previous panel, instantiate the new panel, and refresh the wxDialog by hiding it, then showing it again.
Code Sample
1 from wxPython.wx import *
2
3 class WizardPanel ( wxPanel ) :
4
5 def __init__ ( self, parent ) :
6
7 wxPanel . __init__ ( self, parent, -1 )
8
9 self . parent = parent
10
11 self . nextButton = wxButton ( self, -1, "&Next" )
12 self . previousButton = wxButton ( self, -1, "&Previous" )
13 self . cancelButton = wxButton ( self, wxID_CANCEL, "&Cancel" )
14 self . CreateSubPanel ( )
15 self . divider = wxStaticLine ( self, -1 )
16
17 self . previousButton . Disable ( )
18 self . nextButton . Disable ( )
19
20 self . DefineLayout ( )
21
22 def DefineLayout ( self ) :
23
24 self . SetAutoLayout ( True )
25
26 lc = wxLayoutConstraints ( )
27 lc . left . SameAs ( self . parent, wxLeft )
28 lc . right . SameAs ( self . parent, wxRight )
29 lc . top . SameAs ( self . parent, wxTop )
30 lc . bottom . SameAs ( self . parent, wxBottom )
31 self . SetConstraints ( lc )
32
33 lc = wxLayoutConstraints ( )
34 lc . right . SameAs ( self, wxRight, 10 )
35 lc . width . AsIs ( )
36 lc . height . AsIs ( )
37 lc . bottom . SameAs ( self, wxBottom, 10 )
38 self . nextButton . SetConstraints ( lc )
39
40 lc = wxLayoutConstraints ( )
41 lc . right . SameAs ( self . nextButton, wxLeft, 10 )
42 lc . width . AsIs ( )
43 lc . height . AsIs ( )
44 lc . bottom . SameAs ( self, wxBottom, 10 )
45 self . previousButton . SetConstraints ( lc )
46
47 lc = wxLayoutConstraints ( )
48 lc . right . SameAs ( self . previousButton, wxLeft, 10 )
49 lc . width . AsIs ( )
50 lc . height . AsIs ( )
51 lc . bottom . SameAs ( self, wxBottom, 10 )
52 self . cancelButton . SetConstraints ( lc )
53
54 lc = wxLayoutConstraints ( )
55 lc . right . SameAs ( self, wxRight, 10 )
56 lc . left . SameAs ( self, wxLeft, 10 )
57 lc . height . AsIs ( )
58 lc . bottom . SameAs ( self . nextButton, wxTop, 10 )
59 self . divider . SetConstraints ( lc )
60
61 lc = wxLayoutConstraints ( )
62 lc . right . SameAs ( self, wxRight, 10 )
63 lc . left . SameAs ( self, wxLeft, 10 )
64 lc . top . SameAs ( self, wxTop, 10 )
65 lc . bottom . SameAs ( self . divider, wxTop, 10 )
66 self . subpanel . SetConstraints ( lc )
67
68 def CreateSubPanel ( self ) :
69
70 self . subpanel = wxPanel ( self, -1 )
71
72 if __name__ == "__main__" :
73
74 class WizardPanelOne ( WizardPanel ) :
75
76 def __init__ ( self, parent ) :
77
78 WizardPanel . __init__ ( self, parent )
79 self . parent = parent
80
81 self . nextButton . Enable ( true )
82
83 self . reconvertCheckbox = wxCheckBox ( self . subpanel, -1, "Reconvert file?" )
84
85 class WizardPanelTwo ( WizardPanel ) :
86
87 def __init__ ( self, parent ) :
88
89 WizardPanel . __init__ ( self, parent )
90 self . parent = parent
91
92 self . previousButton . Enable ( true )
93
94 self . label = wxStaticText ( self . subpanel, -1, 'Yet more tedious questions' )
95
96 class MainFrame ( wxFrame ) :
97
98 def __init__ ( self, * args ) :
99
100 wxFrame . __init__ ( self, * args )
101
102 self . wizard = wxDialog ( self, -1, "Sample Alternative Wizard", style = wxCAPTION, size = ( 500, 500 ) )
103 self . wizard . wizardpanel = WizardPanelOne ( self . wizard )
104
105 EVT_BUTTON ( self . wizard, self . wizard . wizardpanel . nextButton . GetId ( ), self . OnNextButton )
106
107 result = self . wizard . ShowModal ( )
108
109 if result == wxID_OK :
110 print 'wizard ok'
111
112 def OnNextButton ( self , event ) :
113
114 self . wizard . wizardpanel . Destroy ( )
115 self . wizard . wizardpanel = WizardPanelTwo ( self . wizard )
116
117 self . wizard . Show ( false )
118 self . wizard . ShowModal ( )
119
120 event . Skip ( )
121
122 app = wxPySimpleApp ( )
123 frame = MainFrame ( None, wxNewId ( ), 'Trial run' )
124
125 frame . Show ( )
126 app . MainLoop ( )
Comments
I welcome your comments. - Bill Bell