Previous | Next | Trail Map | Creating a User Interface (with Swing) | Using the JFC/Swing Packages

A Tour Through "Hello Swing"

The HelloSwing application introduced in the previous section is a simple one. It brings up a window that looks like this:
Each time the user clicks the button, the label is updated. You can find the whole program in HelloSwing.java.

This page discusses the program in detail, explaining the following aspects:

Importing Swing Packages

The following line imports the main Swing package:
import javax.swing.*;

Swing programs also need classes from the two main AWT packages:

import java.awt.*;
import java.awt.event.*;

[PENDING: Refer to package name change.]

Choosing the Look and Feel

Here's the code that HelloSwing uses to set its look and feel:
try {
    UIManager.setLookAndFeel(
        UIManager.getCrossPlatformLookAndFeelClassName());
} catch (Exception e) {
    System.err.println("Couldn't use the cross-platform "
                     + "look and feel: " + e);
}
The preceding code essentially says, "I don't care whether the user has chosen a look and feel -- use the cross-platform look and feel." This rather dictatorial approach makes sense when the program has been designed with a particular look and feel in mind. The cross-platform look and feel is called the JavaTM Look and Feel (nicknamed "Metal").

To find the platform-specific look and feel, use the getSystemLookAndFeelClassName method. On PCs running Windows, this method returns the Windows look and feel. On machines running Solaris, it returns CDE/Motif.

You don't have to set the look and feel that your program uses. By default, every Swing program uses the Metal Look and Feel. The user can also specify a preferred look and feel, the name of which is saved in a file named swing.properties, [PENDING: check filename] and is automatically used by Swing programs that don't set the look and feel.

Setting Up Windows

In general, Swing programs implement their primary windows with JFrame objects. The JFrame class is a subclass of the AWT's Frame class; it adds some features found only in Swing. See How to Make Frames (Main Windows) for information about JFrame features.

Here's the HelloSwing code that deals with its JFrame:

public class HelloSwing extends JFrame implements ActionListener {
    ...
    public HelloSwing() {
        super("HelloSwing");
	...
        JPanel pane = new JPanel();
	...
        setContentPane(pane);
    }
    ...
    public static void main(String[] args) {
        JFrame frame = new HelloSwing();

        WindowListener l = new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        };
        frame.addWindowListener(l);

        frame.pack();
        frame.setVisible(true);
    }
}
The code looks much like the code for using a Frame(in the Creating a User Interface trail). As for a Frame, you instantiate the frame class, add a window listener to it, call pack on it, and then make it visible.

The only difference between the preceding code and the code you'd use for a Frame is in adding components to the JFrame. You can't directly add components to a JFrame. Instead, you either add components to the JFrame's content pane, or you provide a new content pane.

A content pane is a Container that, generally speaking, contains all of the frame's visible components except for the menu bar (if any). To get a JFrame's content pane, use the getContentPane method. To set its content pane, as the preceding example does, use the setContentPane method.

Setting Up Swing Components

The HelloSwing program explicitly instantiates four Swing components: a JFrame, a JButton, a JLabel, and a JPanel. This subsection discusses the button, label, and panel.

Here's the code that initializes the button:

JButton button = new JButton("I'm a Swing button!");
button.setMnemonic('i');
button.addActionListener(this);
button.getAccessibleContext().setAccessibleDescription(
        "When you click this button, the label is updated "
      + "to display the total number of button clicks.");
The first line creates the button. The second sets the letter "i" as the mnemonic that the user can use to simulate a click of the button. For example, in the Metal Look and Feel, typing Alt-i results in a button click. The third line registers an event handler for the button click. You'll see the event handler code in Handling Events. Finally, the next lines describe the button, so that assistive technologies can give help to people trying to use the button. You'll find out more about this in Supporting Assistive Technologies.

Here's the code that initializes and manipulates the label:

...//where instance variables are declared:
private JLabel label;
private static String labelPrefix = "Number of button clicks: ";
private int numClicks = 0;

...//in GUI initialization code:
label = new JLabel(labelPrefix + "0    ");

...//in the event handler for button clicks:
label.setText(labelPrefix + numClicks);

Finally, here's the code that initializes the panel:

JPanel pane = new JPanel();
pane.setBorder(BorderFactory.createEmptyBorder(30, 30, 10, 30));
pane.setLayout(new GridLayout(0, 1));
pane.add(button);
pane.add(label);
The preceding code creates the JPanel object, gives it a border, sets its layout manager to one that will put the panel's contents in a single column, and adds the button and label to the panel.

The code that sets the border uses a feature provided by the JComponent class, which is JPanel's superclass and the source of many of Swing's features. The feature is that each JComponent can have one or more borders. See How to Use Borders for information about using the various types of borders.

The panel in HelloSwing happens to use an invisible border to put extra padding around it: 30 extra pixels on the top, left, and right, and 10 extra pixels on the bottom.

Handling Events

The HelloSwing example contains two event handlers. One handles button clicks (action events) and the other handles window closing. If you're already familiar with the 1.1 AWT event handling system, then the following code from HelloSwing should be familiar:
import java.awt.event.*;
...
public class HelloSwing extends JFrame implements ActionListener {
    ...
        button.addActionListener(this);
    ...
    public void actionPerformed(ActionEvent e) {
        numClicks++;
        label.setText(labelPrefix + numClicks);
    }

    public static void main(String[] args) {
        ...
        WindowListener l = new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        };
        frame.addWindowListener(l);
	...
    }
}

If you aren't familiar with 1.1 event handling, then you can read about it in The 1.1 AWT Event Model(in the Creating a User Interface trail). Swing introduces some new event types, which you'll encounter as you read further in this lesson.

Swing also adds some automatic window-close handling to JFrame, so that you don't always have to implement a window listener. See How to Make Frames (Main Windows) for details.

Dealing with Thread Issues

The HelloSwing program is thread-safe. Once its GUI is visible, its only GUI manipulation (updating the label) occurs in an event handler. Because the event handler runs in the same thread that performs all event handling and painting for the application, there's no possibility that two threads will try to manipulate the GUI at once.

However, it's easy to introduce thread problems into a program. For example, if you add code to the end of HelloSwing's main method that reads a file and then calls label.setText, then you've introduced a potential thread problem, even though your program doesn't create its own threads. The problem might show up if the user presses the button onscreen just before the main method's setText call occurs. In this case, the label's text might be set or drawn improperly, since two threads (the event handling thread and the main thread) would be trying to set the text at once.

See Threads and Swing for information about thread safety in Swing.

Supporting Assistive Technologies

The only code in HelloSwing that exists solely to support assistive technologies is this:
button.getAccessibleContext().setAccessibleDescription(
        "When you click this button, the label is updated "
      + "to display the total number of button clicks.");
In addition, the following lines set information that can be used by assistive technologies:
super("HelloSwing");
JButton button = new JButton("I'm a Swing button!");
label = new JLabel(labelPrefix + "0    ");
label.setText(labelPrefix + numClicks);
The preceding lines set text information to be displayed by the component. Thanks to the accessibility support built into JFrame, JButton, and JLabel (and all the other Swing components), assistive technologies can easily get this text -- or even the text associated with a specific part of a component. Assistive technologies also automatically grab the tool tip text (if any) associated with a component and can use it to describe the component to the user.

You might be wondering what exactly assistive technologies are, and why you should care. Primarily, assistive technologies exist to enable people with permanent or temporary disabilities to use the computer. For example, if you get carpal tunnel syndrome, you can use assistive technologies to accomplish your work without using your hands.

Assistive technologies -- voice interfaces, screen readers, alternate input devices, and so on -- are useful not only for disabled people, but also for people using computers in non-office environments. For example, if you're stuck in a traffic jam, you might use assistive technologies to check your e-mail, using only voice input and output. The accessibility information can be used for other tools, as well, such as automated GUI testers.

Here are a few things you can do to make your program work as well as possible with assistive technologies:


Previous | Next | Trail Map | Creating a User Interface (with Swing) | Using the JFC/Swing Packages