Essentials, Part 1, Lesson 4: Building A User Interface

Training Index

Essentials of the JPL, Part 1

In the last lesson you saw how the Applet class provides a Panel component so you can design the applet's user interface. This lesson expands the basic application from Lessons 1 and 2 to give it a user interface using the Java Foundation Classes (JFC) Project Swing APIs that handle user events.

Project Swing APIs

In contrast to the applet in Lesson 3 where the user interface is attached to a panel object nested in a top-level browser, the Project Swing application in this lesson attaches its user interface to a panel object nested in a top-level frame object. A frame object is a top-level window that provides a title, banner, and methods to manage the appearance and behavior of the window.

The Project Swing code that follows builds this simple application. The window on the left appears when you start the application, and the window on the right appears when you click the button. Click again and you are back to the original window on the left.

Import Statements

Here is the SwingUI.java code. At the top, you have four lines of import statements. The lines indicate exactly which Java API classes the program uses. You could replace four of these lines with this one line: import java.awt.*;, to import the entire awt package, but doing that increases compilation overhead than importing exactly the classes you need and no others.




import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;

Class Declaration

The class declaration comes next and indicates the top-level frame for the application's user interface is a JFrame that implements the ActionListener interface.




class SwingUI extends JFrame
        implements ActionListener{

The JFrame class extends the Frame class that is part of the Abstract Window Toolkit (AWT) APIs. Project Swing extends the AWT with a full set of GUI components and services, pluggable look and feel capabilities, and assistive technology support.

The Java APIs provide classes and interfaces for you to use. An interface defines a set of methods, but does not implement them. The rest of the SwingUI class declaration indicates that this class will implement the ActionListener interface. This means the SwingUI class must implement all methods defined in the ActionListener interface. Fortunately, there is only one, actionPerformed, which is discussed below.

Instance Variables

These next lines declare the Project Swing component classes the SwingUI class uses. These are instance variables that can be accessed by any method in the instantiated class. In this example, they are built in the SwingUI constructor and accessed in the actionPerformed method implementation. The private boolean instance variable is visible only to the SwingUI class and is used in the actionPerformedmethod to find out whether or not the button has been clicked.




   JLabel text, clicked;
   JButton button, clickButton;
   JPanel panel;
   private boolean _clickMeMode = true;

Constructor

The constructor (shown below) creates the user interface components and JPanel object, adds the components to the JPanel object, adds the panel to the frame, and makes the JButton components event listeners. The JFrame object is created in the main method when the program starts.




   SwingUI(){
     text = new JLabel("I'm a Simple Program");
     clicked = new JLabel("Button Clicked");

     button = new JButton("Click Me");
//Add button as an event listener
     button.addActionListener(this);

     clickButton = new JButton("Click Again");
//Add button as an event listener
     clickButton.addActionListener(this);

//Create panel
     panel = new JPanel();
//Specify layout manager and background color
     panel.setLayout(new BorderLayout(1,1));
     panel.setBackground(Color.white);
//Add label and button to panel
     getContentPane().add(panel);
     panel.add(BorderLayout.CENTER, text);
     panel.add(BorderLayout.SOUTH, button);
   }

When the JPanel object is created, the layout manager and background color are specified. The layout manager in use determines how user interface components are arranged on the display area.

The code uses the BorderLayout layout manager, which arranges user interface components in the five areas shown at left. To add a component, specify the area (north, south, east, west, or center).




//Create panel
     panel = new JPanel();
//Specify layout manager and background color
     panel.setLayout(new BorderLayout(1,1));
     panel.setBackground(Color.white);
//Add label and button to panel
     getContentPane().add(panel);
     panel.add(BorderLayout.CENTER, text);
     panel.add(BorderLayout.SOUTH, button);
   }

To find out about some of the other available layout managers and how to use them, see the JDC article Exploring the AWT Layout Managers.

The call to the getContentPane method of the JFrame class is for adding the Panel to the JFrame. Components are not added directly to a JFrame, but to its content pane. Because the layout manager controls the layout of components, it is set on the content pane where the components reside. A content pane provides functionality that allows different types of components to work together in Project Swing.

Action Listening

In addition to implementing the ActionListener interface, you have to add the event listener to the JButton components. An action listener is the SwingUI object because it implements the ActionListener interface. In this example, when the end user clicks the button, the underlying Java platform services pass the action (or event) to the actionPerformed method. In your code, you implement the actionPerformed method to take the appropriate action based on which button is clicked..

The component classes have the appropriate add methods to add action listeners to them. In the code the JButton class has an addActionListener method. The parameter passed to addActionListener is this, which means the SwingUI action listener is added to the button so button-generated actions are passed to the actionPerformed method in the SwingUI object.




     button = new JButton("Click Me");
//Add button as an event listener
     button.addActionListener(this);

Event Handling

The actionPerformed method is passed an event object that represents the action event that occurred. Next, it uses an if statement to find out which component had the event, and takes action according to its findings.




   public void actionPerformed(ActionEvent event){
     Object source = event.getSource();
        if (_clickMeMode) {
          text.setText("Button Clicked");
          button.setText("Click Again");
          _clickMeMode = false;
        } else {
          text.setText("I'm a Simple Program");
          button.setText("Click Me");
          _clickMeMode = true;
        }
   }

You can find information on event handling for the different components in The Java Tutorial section on Event Handling.

Main Method

The main method creates the top-level frame, sets the title, and includes code that lets the end user close the window using the frame menu.




public static void main(String[] args){
//Create top-level frame
  SwingUI frame = new SwingUI();
  frame.setTitle("Example");
//This code lets you close the window
  WindowListener l = new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
  };
    frame.addWindowListener(l);
//This code lets you see the frame
  frame.pack();
  frame.setVisible(true);
 }
}

The code for closing the window shows an easy way to add event handling functionality to a program. If the event listener interface you need provides more functionality than the program actually uses, use an adapter class. The Java APIs provide adapter classes for all listener interfaces with more than one method. This way, you can use the adapter class instead of the listener interface and implement only the methods you need. In the example, the WindowListener interface has 7 methods and this program needs only the windowClosing method so it makes sense to use the WindowAdapter class instead.

This code extends the WindowAdapter class and overrides the windowClosing method. The new keyword creates an anonymous instance of the extended inner class. It is anonymous because you are not assigning a name to the class and you cannot create another instance of the class without executing the code again. It is an inner class because the extended class definition is nested within the SwingUI class.

This approach takes only a few lines of code, while implementing the WindowListener interface would require 6 empty method implementations. Be sure to add the WindowAdapter object to the frame object so the frame object will listen for window events.




   WindowListener l = new WindowAdapter() {
 //The instantiation of object l is extended to 
 //include this code:
     public void windowClosing(WindowEvent e){
        System.exit(0);
     }
   }; 
   frame.addWindowListener(l);

Applets Revisited

Using what you learned in Lesson 3: Building Applets and this lesson, convert the example for this lesson into an applet. Give it a try before looking at the solution.

In short, the differences between the applet and application versions are the following:

  • The applet class is declared public so appletviewer can access it.
  • The applet class descends from Applet and the application class descends from JFrame.
  • The applet version has no main method.
  • The application constructor is replaced in the applet by start and init methods.
  • GUI components are added directly to the Applet; whereas, in the case of an application, GUI components are added to the content pane of its JFrame object.

More Information

For more information on Project Swing, see The JFC Project Swing Tutorial: A Guide to Constructing GUIs.

To find out about some of the other available layout managers and how to use them, see the JDC article Exploring the AWT Layout Managers.