Introduction
Unfortunately, the api docs regarding the wizard class are a bit difficult to understand and code snippets found online sometimes use different namespaces, making it hard to cut and paste the code and have it work without modification. This might be fine for experts, but not for a newbie like myself trying to figure it out last night.
Also, the otherwise nice wizard example in the wxpython demo is buried under various panels and buttons making it hard to separate it from the demo itself.
Here is a mini tutorial with examples on how to use the wizard class, with no cruft to get in the way. First, lets extend the wizard class and make it a tiny bit easier to deal with:
Code Sample
1 class wizard(wx.wizard.Wizard):
2 '''Add pages to this wizard object to make it useful.'''
3 def __init__(self, title, img_filename=""):
4 # img could be replaced by a py string of bytes
5 if img_filename and os.path.exists(img_filename):
6 img = wx.Bitmap(img_filename)
7 else: img = wx.NullBitmap
8 wx.wizard.Wizard.__init__(self, None, -1, title, img)
9 self.pages = []
10
11 def add_page(self, page):
12 '''Add a wizard page to the list.'''
13 if self.pages:
14 previous_page = self.pages[-1]
15 page.SetPrev(previous_page)
16 previous_page.SetNext(page)
17 self.pages.append(page)
18
19 def run(self):
20 self.RunWizard(self.pages[0])
Next, lets make a page class. This class should be modified to your needs and then added to a wizard object defined above.
1 padding = 5
2
3 class wizard_page(wizmod.PyWizardPage):
4 ''' An extended panel obj with a few methods to keep track of its siblings.
5 This should be modified and added to the wizard. Season to taste.'''
6 def __init__(self, parent, title):
7 wx.wizard.PyWizardPage.__init__(self, parent)
8 self.next = self.prev = None
9 self.sizer = wx.BoxSizer(wx.VERTICAL)
10 title = wx.StaticText(self, -1, title)
11 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
12 self.sizer.AddWindow(title, 0, wx.ALIGN_LEFT|wx.ALL, padding)
13 self.sizer.AddWindow(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, padding)
14 self.SetSizer(self.sizer)
15
16 def add_stuff(self, stuff):
17 '''Add additional widgets to the bottom of the page'''
18 self.sizer.Add(stuff, 0, wx.EXPAND|wx.ALL, padding)
19
20 def SetNext(self, next):
21 '''Set the next page'''
22 self.next = next
23
24 def SetPrev(self, prev):
25 '''Set the previous page'''
26 self.prev = prev
27
28 def GetNext(self):
29 '''Return the next page'''
30 return self.next
31
32 def GetPrev(self):
33 '''Return the previous page'''
34 return self.prev
Next, lets start the application:
1 if __name__ == '__main__':
2
3 app = wx.PySimpleApp() # Start the application
4
5 # Create wizard and add any kind pages you'd like
6 mywiz = wizard('Simple Wizard', img_filename='wiz.png')
7 page1 = wizard_page(mywiz, 'Page 1') # Create a first page
8 page1.add_stuff(wx.StaticText(page1, -1, 'Hola'))
9 mywiz.add_page(page1)
10
11 # Add some more pages
12 mywiz.add_page( wizard_page(mywiz, 'Page 2') )
13 mywiz.add_page( wizard_page(mywiz, 'Page 3') )
14
15 mywiz.run() # Show the main window
16
17 # Cleanup
18 mywiz.Destroy()
19 app.MainLoop()
Ok, so that works ... but it doesn't do anything yet. Lets add some event listeners to the wizard and a few functions to handle them:
1 class wizard(wx.wizard.Wizard):
2 def __init__(self, title, img_filename=""):
3
4 # previous code here ...
5
6 # Lets catch the events
7 self.Bind(wizmod.EVT_WIZARD_PAGE_CHANGED, self.on_page_changed)
8 self.Bind(wizmod.EVT_WIZARD_PAGE_CHANGING, self.on_page_changing)
9 self.Bind(wizmod.EVT_WIZARD_CANCEL, self.on_cancel)
10 self.Bind(wizmod.EVT_WIZARD_FINISHED, self.on_finished)
11
12 # Now define some event handler functions from the demo
13 def on_page_changed(self, evt):
14 '''Executed after the page has changed.'''
15 if evt.GetDirection(): dir = "forward"
16 else: dir = "backward"
17 page = evt.GetPage()
18 print "page_changed: %s, %s\n" % (dir, page.__class__)
19
20 def on_page_changing(self, evt):
21 '''Executed before the page changes, so we might veto it.'''
22 if evt.GetDirection(): dir = "forward"
23 else: dir = "backward"
24 page = evt.GetPage()
25 print "page_changing: %s, %s\n" % (dir, page.__class__)
26
27 def on_cancel(self, evt):
28 '''Cancel button has been pressed. Clean up and exit without continuing.'''
29 page = evt.GetPage()
30 print "on_cancel: %s\n" % page.__class__
31
32 # Prevent cancelling of the wizard.
33 if page is self.pages[0]:
34 wx.MessageBox("Cancelling on the first page has been prevented.", "Sorry")
35 evt.Veto()
36
37 def on_finished(self, evt):
38 '''Finish button has been pressed. Clean up and exit.'''
39 print "OnWizFinished\n"
Define whatever behavior you need in these event handlers above.
At this point, you might want to create or copy a little image for use in the wizard. Here I have used the name "wiz.png," but a string of bytes instead would be a useful way to hide the image inside the script itself.
So, lets take a look at our completed wizard.
Complete Source
1 import wx
2 import wx.wizard as wizmod
3 import os.path
4 padding = 5
5
6 class wizard_page(wizmod.PyWizardPage):
7 ''' An extended panel obj with a few methods to keep track of its siblings.
8 This should be modified and added to the wizard. Season to taste.'''
9 def __init__(self, parent, title):
10 wx.wizard.PyWizardPage.__init__(self, parent)
11 self.next = self.prev = None
12 self.sizer = wx.BoxSizer(wx.VERTICAL)
13 title = wx.StaticText(self, -1, title)
14 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
15 self.sizer.AddWindow(title, 0, wx.ALIGN_LEFT|wx.ALL, padding)
16 self.sizer.AddWindow(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, padding)
17 self.SetSizer(self.sizer)
18
19 def add_stuff(self, stuff):
20 '''Add aditional widgets to the bottom of the page'''
21 self.sizer.Add(stuff, 0, wx.EXPAND|wx.ALL, padding)
22
23 def SetNext(self, next):
24 '''Set the next page'''
25 self.next = next
26
27 def SetPrev(self, prev):
28 '''Set the previous page'''
29 self.prev = prev
30
31 def GetNext(self):
32 '''Return the next page'''
33 return self.next
34
35 def GetPrev(self):
36 '''Return the previous page'''
37 return self.prev
38
39
40 class wizard(wx.wizard.Wizard):
41 '''Add pages to this wizard object to make it useful.'''
42 def __init__(self, title, img_filename=""):
43 # img could be replaced by a py string of bytes
44 if img_filename and os.path.exists(img_filename):
45 img = wx.Bitmap(img_filename)
46 else: img = wx.NullBitmap
47 wx.wizard.Wizard.__init__(self, None, -1, title, img)
48 self.pages = []
49 # Lets catch the events
50 self.Bind(wizmod.EVT_WIZARD_PAGE_CHANGED, self.on_page_changed)
51 self.Bind(wizmod.EVT_WIZARD_PAGE_CHANGING, self.on_page_changing)
52 self.Bind(wizmod.EVT_WIZARD_CANCEL, self.on_cancel)
53 self.Bind(wizmod.EVT_WIZARD_FINISHED, self.on_finished)
54
55 def add_page(self, page):
56 '''Add a wizard page to the list.'''
57 if self.pages:
58 previous_page = self.pages[-1]
59 page.SetPrev(previous_page)
60 previous_page.SetNext(page)
61 self.pages.append(page)
62
63 def run(self):
64 self.RunWizard(self.pages[0])
65
66 def on_page_changed(self, evt):
67 '''Executed after the page has changed.'''
68 if evt.GetDirection(): dir = "forward"
69 else: dir = "backward"
70 page = evt.GetPage()
71 print "page_changed: %s, %s\n" % (dir, page.__class__)
72
73 def on_page_changing(self, evt):
74 '''Executed before the page changes, so we might veto it.'''
75 if evt.GetDirection(): dir = "forward"
76 else: dir = "backward"
77 page = evt.GetPage()
78 print "page_changing: %s, %s\n" % (dir, page.__class__)
79
80 def on_cancel(self, evt):
81 '''Cancel button has been pressed. Clean up and exit without continuing.'''
82 page = evt.GetPage()
83 print "on_cancel: %s\n" % page.__class__
84
85 # Prevent cancelling of the wizard.
86 if page is self.pages[0]:
87 wx.MessageBox("Cancelling on the first page has been prevented.", "Sorry")
88 evt.Veto()
89
90 def on_finished(self, evt):
91 '''Finish button has been pressed. Clean up and exit.'''
92 print "OnWizFinished\n"
93
94
95 if __name__ == '__main__':
96
97 app = wx.PySimpleApp() # Start the application
98
99 # Create wizard and add any kind pages you'd like
100 mywiz = wizard('Simple Wizard', img_filename='wiz.png')
101 page1 = wizard_page(mywiz, 'Page 1') # Create a first page
102 page1.add_stuff(wx.StaticText(page1, -1, 'Hola'))
103 mywiz.add_page(page1)
104
105 # Add some more pages
106 mywiz.add_page( wizard_page(mywiz, 'Page 2') )
107 mywiz.add_page( wizard_page(mywiz, 'Page 3') )
108
109 mywiz.run() # Show the main window
110
111 # Cleanup
112 mywiz.Destroy()
113 app.MainLoop()
Hopefully that helped. Please comment if you had problems or how to improve this page.