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.

wxWizard (last edited 2012-09-27 05:44:32 by brn1-v-5-32)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.