Introduction
Java, while only a few years old, is already being deployed in a wide variety of devices. Java exists for mainframes, midrange servers, PCs, and handheld devices. There is even a group currently working on a real-time Java for embedded control applications! Aside from the embedded environment, the vast majority of Java developers will be required to create some type of user interface for their application. For things like configuration tools, a command-line interface works fine (which Java supports, of course). However, for applications deployed to a wide range of users or for applications required to display data, graphical user interfaces work best.
Java supports graphical user interface development through the Abstract Windowing Toolkit, or AWT. The AWT is the Java equivalent of the Microsoft Windows Common Control Library or a Motif widget toolkit. It includes support for simple graphics programming as well as a number of preconstructed components such as button, menu, list, and checkbox classes. The java.awt package is included with the Java 2 SDK and will be the focus of this discussion. Numerous third-party components are available (see links at bottom of this page) for additional GUI functionality.
Java AWT Basics
The AWT allows Java developers to quickly build Java applets and applications using a group of prebuilt user interface components. A number of Java IDE’s are available which support the creation of user interfaces using the AWT by dragging-and-dropping components off a toolbar. It should be noted that these IDE’s actually generate Java code on the fly based on what you do in the graphical design environment. This is in contrast to toolsets such as Microsoft Visual Basic which separate user interface design from the application code. The advantage of the Java approach is that you can edit your GUI either through a graphical IDE or by simply modifying the Java code and recompiling.
The three steps common to all Java GUI applications are:
- 1. Creation of a container
- 2. Layout of GUI components
- 3. Handling of events.
Creating A Container
This container object is actually derived from the java.awt.Container class and is one of (or inherited from) three primary classes: java.awt.Window, java.awt.Panel, java.awt.ScrollPane. The Window class represents a standalone window (either an application window in the form of a java.awt.Frame, or a dialog box in the form of a java.awt.Dialog).
The java.awt.Panel class is not a standalone window in and of itself; instead, it acts as a background container for all other components on a form. For instance, the java.awt.Applet class is a direct descendant of java.awt.Panel.
Laying Out GUI Components
GUI components can be arranged on a container using one of two methods. The first method involves the exact positioning (by pixel) of components on the container. The second method involves the use of what Java calls Layout Managers. If you think about it, virtually all GUIs arrange components based on the row-column metaphor. In other words, buttons, text boxes, and lists generally aren’t located at random all over a form. Instead, they are usually neatly arranged in rows or columns with an OK or Cancel button arranged at the bottom or on the side. Layout Managers allow you to quickly add components to the manager and then have it arrange them automatically. The AWT provides six layout managers for your use:
- java.awt.BorderLayout
- java.awt.FlowLayout
- java.awt.CardLayout
- java.awt.GridLayout
- java.awt.GridBagLayout
- java.awt.BoxLayout
The Container class contains the setLayout() method so that you can set the default LayoutManager to be used by your GUI. To actually add components to the container, we use the container’s add() method: Panel p = new java.awt.Panel(); Button b = new java.awt.Button(“OK”); p.add(b);
Handling Events
Event handling has changed since Java 1.0 was first released in 1995. Originally, JDK 1.0.2 applications handled events using an inheritance model. A container subclassed the action() and handleEvent() methods of its parent and handled the events for all components it contained. For instance, the following code would represent the event handler for a panel containing an OK and a Cancel button: public boolean handleEvent(java.awt.Event e) { if (e.id == java.awt.Event.ACTION_EVENT) { if (e.target == buttonOK) { buttonOKPressed(); } else if (e.target == buttonCancel) ( buttonCancelPressed(); ) } return super.handleEvent(e); }
The problem with this method is that events cannot be delivered to specific objects. Instead, they have to be routed through a universal handler which increases complexity and therefore weakens your design.
Java 1.1 introduced the concept of the event delegation model. This model allows special classes, known as “adapter classes” to be built to be registered with a component in order to handle certain events. The event delegation model uses the model-view controller pattern which separates the view of a component from its data. Using this model requires three simple steps:
- Implement the desired listener interface in your adapter class. Depending on what event you’re handling, a number of listener interfaces are available. These include: ActionListener, WindowListener, MouseListener, MouseMotionListener, ComponentListener, FocusListener, and ListSelectionListener.
- Register the adapter listener with the desired component(s). This can be in the form of an addXXXListener() method supported by the component. Examples include addActionListener(), addMouseListener(), and addFocusListener().
- Implement the listener interface’s methods in your adapter class. It is in this code that you will actually handle the event.
Using the event delegation model allows the developer to separate the component’s display (user interface) from the event handling (application data) which results in a cleaner, more object-oriented design.
Applet Example
The following program was written as a Java applet in order to provide a simple example that makes use of some common AWT components as well as illustrate event-handling concepts.
Java graphical user interface construction is supported in two flavors: the standard AWT “look-and-feel” and a newer layer on top of AWT, known as Swing. The Swing set of components work the same as the standard AWT components but in addition support what Sun calls pluggable look-and-feel. A user interface built using Swing can toggle between look-and-feels (i.e. Windows look to Mac look to Motif look) very simply. Designers are also free to supply their own look-and-feel in order to extend the Swing user interface.
Swing components are included within a larger GUI framework from Sun known as the Java Foundation Classes, or JFC. JFC includes the Swing components along with the Java 2D API, drag-and-drop functionality, and the accessability API. For more information on Swing and JFC, see the Sun Java Foundation Classes Information Page.