THE JAVA ABSTRACT WINDOWING TOOLKIT (AWT)


Contents


Overview

Java's Abstract Windowing Toolkit (AWT) provides support for programs that use Graphical User Interfaces (GUIs), rather than simply communicating with the user via the keyboard or via files. The AWT includes classes for commonly used objects like windows, labels, buttons, and checkboxes. For more in-depth coverage of the AWT, see chapter 13 of Java Programming.

Hello World Example

Here is a new version of the "Hello World" program. Rather than writing to the screen, this version opens a new window and displays "Hello World!" in that window.

Things to note:

  1. The HelloWorld class extends the Frame class. A Frame corresponds to a window on your screen with a title and a border. The way it looks will depend on how your system is set up to display windows (e.g., it may have controls to permit resizing, etc).

  2. In general, a Frame can contain components (like labels and buttons). In this example, the Frame contains a single Label object named text. The Label is added to the Frame using the Frame's add method: "add(text);" as part of the HellowWorld class's constructor function. Because the Frame contains no other objects, the Label expands to fill the whole Frame.

  3. The constructor function must also set the size of the Frame: "setSize( 300, 100 );" (the size is in pixels: 300 wide and 100 high -- the default size is 0 by 0), and must make the Frame visible: "setVisible( true );"

  4. Because this is an application program (not an applet), you must still include a main method. All the main method has to do is create a HelloWorld object, using new: "new HelloWorld();"


TEST YOURSELF #1

Modify the HelloWorld program in each of the following ways:

  1. Instead of always writing "Hello World!" in the new window, write the (single) string that is provided as a command-line argument. So for example, if the user types then the new window contains the text "fishsticks", instead of "Hello World!".

  2. A Label is a subclass of the Component class. Read about the Component methods, and use the appropriate ones so that the background color of the new window is red, and the color of the text is blue. (Don't forget that the values for the colors are members of the Color class, so you need to use Color.red, not just red.)

solution


Example Using Listeners

Below is another version of the HelloWorld program (called Hello1) that demonstrates more of the power of the AWT. This program creates a Frame with two sub-components:

  1. A label containing "Hello World!" as before.
  2. A button labeled "exit". When the user clicks this button with the mouse, the program halts, and the new window is closed.
import java.awt.*;
import java.awt.event.*;

public class Hello1 extends Frame {
    private Label text;
    private Button exitButton;

    // constructor
    public Hello1() {

	// create a label containing "Hello World!", with the text centered
	// and add the label to the top of the Frame
	text = new Label("Hello World!", Label.CENTER);
	add(text, "North");

	// create the exit button and add it to the bottom of the Frame
	exitButton = new Button("exit");
	add(exitButton, "South");

	// create a listener for the exit button that will cause a
	// reaction when the button is clicked (using the mouse), and
	// associate that listener with the exit button
	ExitButtonListener exitListener = new ExitButtonListener();
	exitButton.addActionListener(exitListener);
	
	// set the size of the frame and make it visible
	setSize( 300, 100 );
	setVisible( true );
    }

    // define the listener for the exit button
    class ExitButtonListener implements ActionListener {
	public void actionPerformed(ActionEvent e) {
	    // this method will be called when the exit button is clicked;
	    // end execution of this program
	    System.exit(0);
	}
    }

    // main
    public static void main( String[] args ) {
	new Hello1();
    }
}
This example introduces the concept of a listener, discussed below.

Listeners

When you write a Graphical User Interface, you usually want your program to respond to user actions, like pushing a button or typing in text. The mechanism that the Java AWT provides to support this is the creation of Listeners, which have methods that are invoked in response to user actions. Each component can have an associated Listener of the appropriate type that will respond to user actions involving that component.

There are 3 main kinds of Listeners:

  1. ActionListener, associated with a Button
  2. ItemListener, associated with a Checkbox or a List
  3. TextListener, associated with a TextField or a TextArea

These Listeners are all interfaces (defined in java.awt.event). To create your own Listener, you must define a class that implements one of these interfaces. For example, in the Hello1 program, the line:

starts the definition of class ExitButtonListener, which is an implementation of the ActionListener interface.

Each kind of Listener has a method (which you must define) that is called when a particular user action is performed on a component associated with that Listener:

The components that can have associated Listeners all have methods called addXXXListener, where XXX is the kind of Listener (Action, Item, or Text). To associate a Listener with a component, call the component's addXXXListener method with the Listener object as the argument. For example, the call:

associates the ActionListener named exitListener with the Button object named exitButton.


TEST YOURSELF #2

Modify the Hello1 program so that the Frame contains two components:

  1. A TextField that initially contains "Hello World!". (Note that the user will be able to modify the text in this TextField.)
  2. A button labeled "reset". When the user clicks this button with the mouse, the text in the TextField is reset to contain "Hello World!". (Note: to reset the text, you will need to use a method of the TextField's parent class.)

solution


Example Using Layout

Below is a more complicated example program. This program creates a Frame with three sub-components:

  1. A Label, containing the string "This text will change font".
  2. A List, containing three items: the strings "bold", "italic", and "bold italic".
  3. A Panel, which in turn contains two sub-components, both Buttons (a "reset font" button and an "exit" button).

Selecting one of the List items (by clicking on it with the mouse) causes the text in the Label to change to the corresponding font. Clicking on the "reset font" button causes the text to change back to plain font. Clicking on the "exit" button terminates the program.

This example uses more components, uses Listeners more extensively, and also introduces layouts, discussed below. First, though, consider the following issue, brought up by this example:

If you have several components of the same type (e.g., several Buttons) and you want to respond to user actions involving each of those components, you have two choices:

  1. Write a different Listener for each component, specialized to respond to user actions on that particular component. This is the approach that was taken in the ChangeFont program, where two different ActionListeners were defined for the two buttons (the "reset font" button and the "exit" button).

  2. Write a single Listener for all of the components. In the method that is called in response to a user action, determine which component was actually involved, and respond accordingly. Each Listener method (actionPerformed, itemStateChanged, and textValueChanged) has a parameter that is a subclass of the class java.util.EventObject. This class includes the method getSource, which returns the actual object to which the user action was applied. For example, the following ActionListener could be associated with both the "reset font" and the "exit" buttons:

Layouts

Frames and Panels are both subclasses of the Container class. These classes can contain sub-components (like Buttons, Lists, and Panels), and they have associated layout mechanisms (schemes for organizing their sub-components).

There are 5 kinds of layouts (only the first 3 will be discussed here):

  1. Border Layouts
  2. Flow Layouts
  3. Grid Layouts
  4. Grid-Bag Layouts
  5. Card Layouts
A container that uses the Border Layout can contain up to 5 sub-components, organized as shown below: When a component is added to a container that uses the Border Layout, the area in which to position the component can be specified. For example, in the program above, the statement "add(msgLabel, "North");" is used to add the Label component to the top (North) of the Frame. If one or more of the 5 areas are not used, the other areas expand to fill up the space. The Border Layout is the default layout for Frames.

A container that uses the Flow Layout can contain any number of sub-components. They are organized in rows across the container. If there is not enough room for all of the sub-components in a single row, then a second row is started, etc. Whether the items in an incomplete row are left-justified, right-justified, or centered can be specified when the Flow Layout is selected (see below). The Flow Layout is the default layout for Panels.

The sub-components in a Grid Layout are organized into an N-by-M grid, where N and M are specified when the Grid Layout is selected. When a component is added to a container using the Grid Layout, it goes into the next column of the current row (or the first column of the next row if the current row is full); it is not possible to leave empty spaces or to add components out of order.

A particular layout is selected for a container using the container's setLayout method. The argument to setLayout is a LayoutManager object. For example, the statement:

sets the layout of the buttonPanel object to be a Grid Layout that contains 1 row and 2 columns. The statement: sets the layout of the buttonPanel object to be a Flow Layout in which items in an incomplete row are centered.


TEST YOURSELF #3

Modify the ChangeFont program in each of the following ways:

  1. Change the program so that the Frame it creates uses a Flow Layout (rather than the default Border Layout). (Remember that when you add components to the Frame under the Flow Layout you simply add them, you do not specify which area of the Frame they should occupy.)

    Run the two versions of ChangeFont, and compare what happens when you resize the newly created window.

  2. Change the program so that the Frame it creates contains Checkboxes to control the fonts rather than a List. In particular, the center part of the Frame should contain a Panel that in turn contains 3 Checkboxes labeled: "bold font", "italic font", and "bold italic font". Make the 3 Checkboxes part of a CheckboxGroup so that at most one Checkbox can be in the "selected" position. (If no Checkboxes are selected, the font should be plain font.)

solution


Graphics

Java.awt also provides support for simple graphics. In particular, every component has a paint method, which is called to display the component on the screen. It is possible to redefine the paint method for any class that extends a component class. For example, here is a program that defines the class Draw as a subclass of Frame, and redefines the paint method to draw a stick figure:

Note that the paint method has one parameter, a
Graphics object. In the example, the actual parameter is the "graphics context" associated with the Frame. By calling the various draw methods of the Graphics object, you can cause various shapes to appear in the Frame.

As mentioned above, you can redefine the paint method of any subclass of a Component. So, for example, you could create a button with the stick figure on it (in addition to the button label) by defining a subclass of Button, and redefining its paint method:

More typically, a subclass of the Canvas component (a blank rectangle) is used for drawing.

Solutions to Self-Study Questions

Test Yourself #1

Test Yourself #2

Test Yourself #3