Differences between revisions 2 and 3
Revision 2 as of 2008-03-11 10:50:23
Size: 9812
Editor: localhost
Comment: converted to 1.6 markup
Revision 3 as of 2012-09-27 05:44:32
Size: 9898
Editor: brn1-v-5-32
Comment: comments in code have to be closed in three apostrophes
Deletions are marked like this. Additions are marked like this.
Line 14: Line 14:
    'Add pages to this wizard object to make it useful.'     '''Add pages to this wizard object to make it useful.'''
Line 24: Line 24:
        'Add a wizard page to the list.'         '''Add a wizard page to the list.'''
Line 56: Line 56:
        'Add additional widgets to the bottom of the page'         '''Add additional widgets to the bottom of the page'''
Line 60: Line 60:
        'Set the next page'         '''Set the next page'''
Line 64: Line 64:
        'Set the previous page'         '''Set the previous page'''
Line 68: Line 68:
        'Return the next page'         '''Return the next page'''
Line 72: Line 72:
        'Return the previous page'         '''Return the previous page'''
Line 121: Line 121:
        'Executed after the page has changed.'         '''Executed after the page has changed.'''
Line 128: Line 128:
        'Executed before the page changes, so we might veto it.'         '''Executed before the page changes, so we might veto it.'''
Line 135: Line 135:
        'Cancel button has been pressed. Clean up and exit without continuing.'          '''Cancel button has been pressed. Clean up and exit without continuing.'''
Line 145: Line 145:
        'Finish button has been pressed. Clean up and exit.'          '''Finish button has been pressed. Clean up and exit.'''
Line 180: Line 180:
        'Add aditional widgets to the bottom of the page'         '''Add aditional widgets to the bottom of the page'''
Line 184: Line 184:
        'Set the next page'         '''Set the next page'''
Line 188: Line 188:
        'Set the previous page'         '''Set the previous page'''
Line 192: Line 192:
        'Return the next page'         '''Return the next page'''
Line 196: Line 196:
        'Return the previous page'         '''Return the previous page'''
Line 201: Line 201:
    'Add pages to this wizard object to make it useful.'     '''Add pages to this wizard object to make it useful.'''
Line 216: Line 216:
        'Add a wizard page to the list.'         '''Add a wizard page to the list.'''
Line 227: Line 227:
        'Executed after the page has changed.'         '''Executed after the page has changed.'''
Line 234: Line 234:
        'Executed before the page changes, so we might veto it.'         '''Executed before the page changes, so we might veto it.'''
Line 241: Line 241:
        'Cancel button has been pressed. Clean up and exit without continuing.'         '''Cancel button has been pressed. Clean up and exit without continuing.'''
Line 251: Line 251:
        'Finish button has been pressed. Clean up and exit.'         '''Finish button has been pressed. Clean up and exit.'''

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.