== 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 == {{{ #!python from wxPython.wx import * class WizardPanel ( wxPanel ) : def __init__ ( self, parent ) : wxPanel . __init__ ( self, parent, -1 ) self . parent = parent self . nextButton = wxButton ( self, -1, "&Next" ) self . previousButton = wxButton ( self, -1, "&Previous" ) self . cancelButton = wxButton ( self, wxID_CANCEL, "&Cancel" ) self . CreateSubPanel ( ) self . divider = wxStaticLine ( self, -1 ) self . previousButton . Disable ( ) self . nextButton . Disable ( ) self . DefineLayout ( ) def DefineLayout ( self ) : self . SetAutoLayout ( True ) lc = wxLayoutConstraints ( ) lc . left . SameAs ( self . parent, wxLeft ) lc . right . SameAs ( self . parent, wxRight ) lc . top . SameAs ( self . parent, wxTop ) lc . bottom . SameAs ( self . parent, wxBottom ) self . SetConstraints ( lc ) lc = wxLayoutConstraints ( ) lc . right . SameAs ( self, wxRight, 10 ) lc . width . AsIs ( ) lc . height . AsIs ( ) lc . bottom . SameAs ( self, wxBottom, 10 ) self . nextButton . SetConstraints ( lc ) lc = wxLayoutConstraints ( ) lc . right . SameAs ( self . nextButton, wxLeft, 10 ) lc . width . AsIs ( ) lc . height . AsIs ( ) lc . bottom . SameAs ( self, wxBottom, 10 ) self . previousButton . SetConstraints ( lc ) lc = wxLayoutConstraints ( ) lc . right . SameAs ( self . previousButton, wxLeft, 10 ) lc . width . AsIs ( ) lc . height . AsIs ( ) lc . bottom . SameAs ( self, wxBottom, 10 ) self . cancelButton . SetConstraints ( lc ) lc = wxLayoutConstraints ( ) lc . right . SameAs ( self, wxRight, 10 ) lc . left . SameAs ( self, wxLeft, 10 ) lc . height . AsIs ( ) lc . bottom . SameAs ( self . nextButton, wxTop, 10 ) self . divider . SetConstraints ( lc ) lc = wxLayoutConstraints ( ) lc . right . SameAs ( self, wxRight, 10 ) lc . left . SameAs ( self, wxLeft, 10 ) lc . top . SameAs ( self, wxTop, 10 ) lc . bottom . SameAs ( self . divider, wxTop, 10 ) self . subpanel . SetConstraints ( lc ) def CreateSubPanel ( self ) : self . subpanel = wxPanel ( self, -1 ) if __name__ == "__main__" : class WizardPanelOne ( WizardPanel ) : def __init__ ( self, parent ) : WizardPanel . __init__ ( self, parent ) self . parent = parent self . nextButton . Enable ( true ) self . reconvertCheckbox = wxCheckBox ( self . subpanel, -1, "Reconvert file?" ) class WizardPanelTwo ( WizardPanel ) : def __init__ ( self, parent ) : WizardPanel . __init__ ( self, parent ) self . parent = parent self . previousButton . Enable ( true ) self . label = wxStaticText ( self . subpanel, -1, 'Yet more tedious questions' ) class MainFrame ( wxFrame ) : def __init__ ( self, * args ) : wxFrame . __init__ ( self, * args ) self . wizard = wxDialog ( self, -1, "Sample Alternative Wizard", style = wxCAPTION, size = ( 500, 500 ) ) self . wizard . wizardpanel = WizardPanelOne ( self . wizard ) EVT_BUTTON ( self . wizard, self . wizard . wizardpanel . nextButton . GetId ( ), self . OnNextButton ) result = self . wizard . ShowModal ( ) if result == wxID_OK : print 'wizard ok' def OnNextButton ( self , event ) : self . wizard . wizardpanel . Destroy ( ) self . wizard . wizardpanel = WizardPanelTwo ( self . wizard ) self . wizard . Show ( false ) self . wizard . ShowModal ( ) event . Skip ( ) app = wxPySimpleApp ( ) frame = MainFrame ( None, wxNewId ( ), 'Trial run' ) frame . Show ( ) app . MainLoop ( ) }}} === Comments === I welcome your comments. - [[Bill Bell]]