Tutorial

JWizard

Creating the JWizardDialog

To create a Wizard, begin by creating a storyboard, sketching each step and the sequence through the steps. The sequencing may depend on the information users supply as they proceed through the Wizard. Number each step, from 0 to n, roughly following the flow from beginning to end.

Now you're ready to create your Wizard class. The basic pattern is:

public class SampleWizard
    extends JWizardDialog
{


public SampleWizard(Frame owner) {
    super(owner, "Sample Wizard", true);

    // Set the logo image

    URL url = getClass().getResource("SampleWizard.gif");
    setWizardIcon(new ImageIcon(url));

    // Create each step

    addWizardPanel(new Step0());
    addWizardPanel(new Step1());
    addWizardPanel(new Step2());
    ...
    
    // Make the dialog visible

    pack();
    setVisible(true);
}

}

Each Wizard is a subclass of JWizardDialog. In this case, the sample wizard will be the child of a Frame. This will center the Wizard over the Frame. If the Frame is null, the Wizard will be centered in the middle of the screen. You can turn off the centering behavior by calling disableCentering() before calling setVisible().

The dialog title will be "Sample Wizard" and the dialog will be modal (which is fairly standard for Wizards). An icon is added to the Wizard and will be displayed on the left side of the dialog.

Note that each Wizard step is a separate class that is instantiated and added to the dialog. The class names are arbitrary, but the first step will be identified as step 0, so the above naming makes it easy to associate a step with its corresponding class.

The step classes can be created however you like, but my recommendation is that they be inner classes of the JWizardDialog. This makes it very easy for global information to be accumulated in a central place (the JWizardDialog) and accessed by all steps.

Creating the Wizard Steps

The basic pattern for a Wizard step is as follows:

private class Step0
      extends JWizardPanel
{

public
Step0()
{
    setStepTitle("Sample Wizard Step 0");

    JPanel contentPane = getContentPane();
    ...

    // Set the previous and next steps

    setBackStep(-1);
    setNextStep(1);
}

}

Each step is a subclass of JWizardPanel. You will normally start by setting the title for this specific step. Then you will construct all the appropriate components for the step and add them to the JPanel obtained by calling getContentPane() (don't add them directly to the JWizardPanel).

You end each step constructor by calling setBackStep() and setNextStep(). This defines the flow from this panel to the previous and next panels. A previous panel of -1 means that we are on the first panel; a -1 for the next panel means we are on the last panel. Any other number identifies the step we will sequence back or forwards to.

If you need more dynamic sequencing, you will set up the default sequence in the constructor. Then you will override the back() or next() methods. You would determine the correct previous or next step (calling setBackStep() or setNextStep()) and then call super.back() or super.next().

This also allows you to perform error checking. You override the next() method and perform error checking based on the user's step entries. If there is an error, you can display an error dialog and return without calling super.next(). This will leave the step unchanged.

The next() method is also a convenient place to read the user's entries and copy them into JWizardDialog fields so that the information is globally available to all steps.

If you have a complicated Wizard with many steps and lots of components, it may take a while to display if you construct each panel in the JWizardPanel constructor. You perform a delayed construction by overriding makingVisible(). makingVisible() is called just prior to displaying the step, so you'll need to make sure you construct the panel only the first time its called.

This will speed up the initial appearance of the Wizard, but it will make it difficult to size the dialog properly (the dialog should be large enough to accommodate the largest panel). You may think you can manually set the size by calling setSize() on the JWizardDialog. This is not a good idea. There are various circumstances which may change the size needed:

  • If the application is internationalized, the translated labels may be longer than expected.
  • If the application is designed for people with poor vision, you may want to allow for larger font sizes.
  • You may also want larger font sizes for demo purposes (showing the application to a group of people gathered around a display).

JWizardDialog does make allowances for panels created in makingVisible(). Before each panel is displayed, it checks the preferred size against the current size. If the preferred size is bigger, it will increase the dialog's size to match. It will never decrease the size—this minimizes the amount of size changes the dialog goes through.

Handling Finish and Cancel

In JWizardDialog, the finish() and cancel() methods are called when the Finish and Cancel buttons are called, respectively. Each of these methods calls dispose(). You may want to override them. For instance, finish() may want to take all the user's input and do something with it. In cancel(), you may want to query the user to confirm the cancellation. Call super.cancel() if confirmed or else just return.

Handling Help

You add a Help button by calling addHelpButton() in the JWizardDialog constructor. If all Wizard panels have the same help message, you would override help() in the JWizardDialog class. Otherwise, each step should over JWizardPanel's help() method.

Sequencing Options

In general, the sequencing is handled by each step. This is usually the easiest way to do it as each step usually has the information it needs to decide where to go next. However, if you need more central control of the sequencing algorithm, you can override switchToStep() in the JWizardDialog. This method receives the current step value and the requested next step (from the JWizardPanel). Note that the "next" step is the step selected by the user pressing either the Back or Next button. You can change the change the next step value based on whatever criteria you want.

Other Options

In most Wizards, the Finish button is enabled only on the last step. But some Wizards allow the user to call Finish while steps still remain. The information gathered in the remaining steps is defaulted. If you have this model, call setEarlyFinish() in the JWizardDialog.

In some Wizards, the last step is simply where all the necessary user information has been gathered—pressing Finish begins processing the information. In other Wizards, actions may be performed as the Wizard proceeds and the last step is simply to confirm completion of the task. In this latter case, call disableCancelAtEnd() in the JWizardDialog. This disables the Cancel button on the last step.

Summary

The JWizard components are designed to be easy to use. In most cases you will override just a few methods. The rest will normally do the right thing. After reading this tutorial, you should examine the example program provided which exercises many of the features of JWizard.