Graphical User Interfaces

A graphical user interface (GUI, pronounced "GOO-ee"") is intended to present a user-friendly mechanism for interacting with an application. GUIs are built from GUI components. A layout manager controls where the components are located in the window. When a user interacts with a component, an event object is created. This object is dispatched (passed as a parameter) to an event handler (also called an event listener), which is the code that processes the event.

The programs discussed below are in this Java project. This project has one feature that you might not have seen yet. The four different applications are structured into four packages: simplewindow, buttondemo, componentdemo, and listenerdemo. For a given package named foo, the source files will be in the src/foo directory, and the compiled files will be in the bin/foo directory. Also note the use of the package keyword at the top of each .java file.

Model-View-Controller (MVC) Design Pattern

A Java application with a GUI will typically consist of several components. A popular software design pattern for this type of software is the Model-View-Controller pattern. It separates the application logic from the user interface and the control between the user interface and the application logic.

In a Java application, the model might be implemented as a single class or multiple classes. Similarly, the view might be implemented as a single class or multiple classes. Ditto for the controller. The communications between the model, view and controller can be implemented in several ways as well. There are many MVC tutorials, such as Java SE Application Design With MVC and Model-View-Controller (MVC) Structure.

In this page, we focus on the view design (in Java, the window and the components placed inside a window) and the controllers (in Java, the controller typically consists of subclasses of EventListener).

Displaying a Window

The following code shows how to create and display a simple window.

import javax.swing.JFrame;

public class SimpleWindow extends JFrame {
    public SimpleWindow() {
        super("This is a SimpleWindow");
    }

    public static void main(String[] args) {
        SimpleWindow window = new SimpleWindow();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setSize(400, 300);
        window.setVisible(true);
    }
}

Note that SimpleWindow is a subclass of JFrame. The constructor sets the title of the window. The main method shows the typical steps to start a window: create the window object, tell the program to exit when the window is closed, set the initial size of the window, and display the window.

Demonstration of a Component and an Event Handler

The book contains several useful examples of window components and event handlers. You should run some of them and try making changes to understand how they work. However, the book likes to use inner classes and anonymous inner classes in order to implement the event handler in the same file as the component being demonstrated.

Our approach will be put the event handlers (corresponding to the controller) into separate .java files. One example is the DemoButton class and the DemoButtonHandler class (this is in the buttondemo package of the chapter12 project). This is a revision of the ButtonFrame and ButtonTest classes in the book.

Like SimpleWindow, the DemoButton class extends JFrame. The constructor:

Clicking a button results in creating an event object (in this case, an ActionEvent object). An ActionListener object is needed to process this event (in this case, DemoButtonHandler implements ActionListener). The addActionListener method is used to register the event handler (the DemoButtonHandler object) with the component (the JButton object). This will ensure that any clicks on the JButton will result in an event object that will be passed to the actionPerformed method of the DemoButtonHandler.

The DemoButtonHandler class implements the ActionListener interface, which requires an actionPerformed method with an ActionEvent parameter. The constructor stores the button that the event handler is listening to (this can also be accessed by event.getSource() in the actionPerformed method). The actionPerformed method contains the code that processes the event. In this case, it creates a pop-up window that contains the text of the button.

Notice that in this example, there is no model. The click of a button does not change anything in this application. Should there be a model, the DemoButtonHandler (or another ActionListener) will need to pass the event and the control to a method of the model. This may cause the model to change its data and to send message to the view to change the display.

Demonstration of Complex Layouts

Complex GUIs often require that each component be placed in a specific location. They often consist of multiple panels, with each panel’s components arranged in a specific layout. A JFrame object can contain JPanel objects, which in turn may have components, including other JPanel objects. JFrame and JPanel along with layout managers (such as BorderLayout and GridLayout) can be used to create a more complex layout in which several components are in a specific area of another container.

The DemoComponents class is an example of the layout of multiple components. This class is in the componentdemo package of the chapter12 project.

The default layout manager for a JFrame is BorderLayout, which divides the window into five areas.

The first section of the constructor's code in DemoComponents creates JPanels (panelNorth, panelEast, panelWest, panelCenter) for four of these areas.

The code for panelNorth uses the GridLayout manager to divide this JPanel into a 2x2 grid. Four components are added to panelNorth, in order: a JLabel, a JTextField, another JLabel, and a JPasswordField.

After the following section of code adds a JLabel into the south region of the JFrame. The window now has this arrangement:

The code for panelEast uses the GridLayout manager to divide this JPanel into a 4x1 grid with some spacing. Two JButtons and two JCheckBoxes are added to the panel.

The code for panelWest creates a JList. It uses JScrollPane to make it scrollable. Finally, it adds this object to the JPanel. [Note: FlowLayout is the default layout for a JPanel.]

Except for modifying the background color, panelCenter is left alone. This is the final configuration of the window:

Demonstration of Event Handlers

A demonstration of event handlers/listeners is contained in the demolistener package.

The DemoListeners class includes the code from DemoComponents. DemoListeners also has code that registers an event handler for each window component that the user can interact with. See the last section of code in DemoListeners. A new event handler is registered for each interactive window component. The statusBar is used to indicate the last event that has occurred.

The SimpleTextFieldListener class implements the ActionListener interface. Its constructor requires a JTextField (the component it listening to) and a JLabel (to report on any event). This class can also be used for a JPasswordField because JPasswordField is a subclass of JTextField. When the user enters a return in a JTextField (and if an ActionListener is registered), an ActionEvent is created and dispatched to the actionPerformed method of the event handler.

The SimpleButtonListener class implements ActionListener. Its constructor requires an AbstractButton (the component it listening to) and a JLabel (to report on any event). This class can also be used for a JButton because JButton is a subclass of AbstractButton. When the user clicks on an AbstractButton (and if an ActionListener is registered), an ActionEvent is created and dispatched to the actionPerformed method of the event handler.

The SimpleItemListener class implements ItemListener. Its constructor requires a JCheckBox (the component it listening to) and a JLabel (to report on any event). When the user checks or unchecks a JCheckBox (and if an ItemListener is registered), an ItemEvent is created and dispatched to the itemStateChanged method of the event handler.

The SimpleListListener class implements ListSelectionListener. Its constructor requires a JList (the component it listening to) and a JLabel (to report on any event). When the user select an item from a JList (and if a ListSelectionListener is registered), an ListSelectionEvent is created and dispatched to the valueChanged method of the event handler.

The SimpleMouseListener class implements two interfaces: MouseListener and MouseMotionListener. Its constructor requires a JLabel (to report on any event). Within the methods, the object being listened to can be obtained by event.getSource(). There are four methods to implement for MouseListener: mousePressed, mouseReleased, mouseEntered, mouseExited, and two methods to implement for MouseMotionListener: mouseMoved and mouseDragged. When the user's mouse interacts with the JPanel, a MouseEvent is created and dispatched to the appropriate method of the event handler. One can also obtain which mouse buttons were pressed or released from a MouseEvent.