Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Speed up your Swing GUI construction with better building blocks

Use two helper classes to reduce dialog development time

  • Print
  • Feedback

Page 7 of 8

public class CustomerDialog extends StandardDialog
{
    private JTextField myCustomerCodeField = new JTextField();
    private JTextField myNameField = new JTextField();
    private JTextArea myAddressField = new JTextArea(3, 20);
    ...

private LabelledItemPanel myContentPane = new LabelledItemPanel();
public CustomerDialog() { init(); }
private void init() { setTitle("Customer Dialog");
myContentPane.setBorder(BorderFactory.createEtchedBorder());
myContentPane.addItem("Customer Code", myCustomerCodeField); myContentPane.addItem("Name", myNameField); myContentPane.addItem("Address", new JScrollPane(myAddressField, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER)); ...
setContentPane(myContentPane); }
public CustomerData getCustomerData() { CustomerData customerData = new CustomerData();
customerData.myCustomerCode = myCustomerCodeField.getText(); customerData.myName = myNameField.getText(); customerData.myAddress = myAddressField.getText(); ...
return customerData; } }
// A method in some class using the CustomerDialog { CustomerDialog dialog = new CustomerDialog();
dialog.pack();
dialog.show();
if(!dialog.hasUserCancelled()) { CustomerData customerData = dialog.getCustomerData();
// Process the data } }


If data validation needs to be performed before the dialog closes, then the isValidData() method should be overridden. An example of this is given below:

protected boolean isValidData()
{
    if(myCustomerCodeField.getText().equals(""))
    {
        JOptionPane.showMessageDialog(this,
            "Please enter a Customer Code",
            "Blank Customer Code",
            JOptionPane.WARNING_MESSAGE);

myCustomerCodeField.requestFocus();
return false; }
if(myNameField.getText().equals("")) { JOptionPane.showMessageDialog(this, "Please enter a Name", "Blank Name", JOptionPane.WARNING_MESSAGE);
myNameField.requestFocus();
return false; }
return true; }


StandardDialog behind the scenes

This section explains how StandardDialog works. The appearance and behavior of StandardDialog is set up in the init() method shown below:

    private void init()
    {
        setModal(true);
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

// Setup the internal content pane to hold the user content pane // and the standard button panel
JPanel internalContentPane = new JPanel();
internalContentPane.setLayout( new BorderLayout(COMPONENT_SPACING, COMPONENT_SPACING));
internalContentPane.setBorder( BorderFactory.createEmptyBorder(COMPONENT_SPACING, COMPONENT_SPACING, COMPONENT_SPACING, COMPONENT_SPACING));
// Create the standard button panel with "Ok" and "Cancel"
Action okAction = new AbstractAction("Ok") { public void actionPerformed(ActionEvent actionEvent) { if(isValidData()) { myIsDialogCancelled = false;
dispose(); } } };
Action cancelAction = new AbstractAction("Cancel") { public void actionPerformed(ActionEvent actionEvent) { myIsDialogCancelled = true;
dispose(); } };
JPanel buttonPanel = new JPanel();
buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
buttonPanel.add(new JButton(okAction)); buttonPanel.add(new JButton(cancelAction));
internalContentPane.add(buttonPanel, BorderLayout.SOUTH);
// Initialise the user content pane with a JPanel
setContentPane(new JPanel(new BorderLayout()));
super.setContentPane(internalContentPane);
// Finally, add a listener for the window close button. // Process this event the same as the "Cancel" button.
WindowAdapter windowAdapter = new WindowAdapter() { public void windowClosing(WindowEvent windowEvent) { myIsDialogCancelled = true;
dispose(); } };
addWindowListener(windowAdapter); }


The init() is called from the constructor. The method does the following:

  • Sets up actions for the Ok and Cancel buttons. These actions set the field myIsDialogCancelled to indicate which button has been pressed and then call dispose, which causes the show() method to unblock. The method hasUserCancelled() checks the value of myIsDialogCancelled as shown in the usage example.

  • Builds the two buttons and ties them to the actions. The two buttons are added to a panel, and the panel is then added to the dialog.

  • Sets up an event handler for the close window event. This event handler performs the same processing as the action for the Cancel button.


Note: Download the full source code for LabelledItemPanel and StandardDialog from Resources.

Advantages

We have saved substantial development time with this approach. The average time spent building a panel using an IDE GUI builder was between one and three hours depending on the number of fields on the panel. Using our LabelledItemPanel class, the panels were constructed in less than 20 minutes. We have used LabelledItemPanel 35 times.

The other advantages of this approach include:

  • Absolutely no layout constraints need to be understood or specified. This allows developers with little Swing knowledge to quickly construct user interfaces.

  • Consistency of data entry panels and dialogs, both for users and developers.

  • Reordering the fields is simple. You only need to reorder. addItem() calls. You do not have to adjust constraints on all of the reordered fields and labels.

  • The layout and properties for all entry panels can be changed centrally.

  • No unnecessary references are held for labels.


Further enhancements

Our simple classes could be further enhanced to include the following:

  • Print
  • Feedback

Resources