Copyright Chris Johnson, 1998.
This course must NOT be used for any commercial purposes without the express per mission of the author.

Human Computer Interface Design Using Java

Chris
USING THE ABSTRACT WINDOW TOOLKIT (Part 2)
by

Chris Johnson



Using the Abstract Window Toolkit

This section goes on to describe the key features of the Java AWT environment. The initial section describes how events are used to inform application programs about user input and for application programs to affect the display. This purely technical descriptions leads onto section that explore both the design and the programming aspects of various interface features including buttons, menus and forms.


The AWT Classes

There are four main classes in AWT:

The java.awt.Component class is, therefore, fundamental to the AWT in Java. The structure of this class can be illustrated as follows:
                                     Object
                                        |
                                    Component
                                        |
--------------------------------------------------------------------------------
Canvas  Scrollbar  Container  Button  Checkbox  TextComponent  Label  List  Choice
                       |                             |
                  -----------                   -----------
              Panel         Window       TextArea        TextField
                              |
                          ----------
                     Dialog       Frame
                        |
                     FileDialog
The only exception to the classes shown in this diagram are for Menus and Menu items. This difference can be explained by again looking at Word running under
WindowsNT and a Macintosh. There are pronounced differences in the ways that different native platforms implement menus. In some systems it is possible to set the background colour of a menu, in other it is not. Menus, therfore, form part of java.awt.MenuComponent rather than java.awt.Component:

              Object
                 |
           MenuComponent
                 |
            ------------
           |            |
        MenuItem     MenuBar
           |
          ----
         |    |
       Menu CheckboxMenuItem

Each component has a corresponding native peer so that it can be implemented on particular platforms. They also have a number of attributes that can be summarised as follows:

As the names suggests, the container class provides a means of "grouping" multiple components. For instance, an applet may contain a number of buttons. Components can be added to a container. This can be thought of as a list. The order of the list determine the front to back order in which the components are presented on the screen. This is important is one component is not to obscure another. If no index is specified when adding a component to a container, it will be added to the end of the list which represents the bottom of the stacking order. There are a number of different subclasses to Container.

        Container
            |
        --------------------------------------------
     Window           Applet         Panel     Scrollpane
	|
  -------------
Frame       Dialog
               |
           FileDialog
Note that a Frame can have a menubar but that an Applet may not. A window can have no menu or border and so Frames and Dialogs are used more frequently. For instance, the following code creates a Frame with the title "Warning". The size of the frame is defined in terms of two constants (width and height), these can be thought of as pixels.
/*
* A frame 
*
* Author: Chris Johnson (johnson@dcs.gla.ac.uk)
* Last revision date: 11/10/98
*
* Produces a warning window on the screen
*
* Beware - there is no way of closing the frame!
* see later section on event handling...
*/
 
import java.awt.*;
 
public class SimpleWarningFrame extends Frame {
 
static private final int frame_height = 150;
static private final int frame_width = 250;
 
public SimpleWarningFrame () {
        setBackground(Color.red);
        setForeground(Color.black);
	setTitle("Warning");
        resize(frame_width, frame_height);
}
 
   public static void main (String[] args){
 
        Frame f= new SimpleWarning();
        f.show();
   }
}

Containers simply provide a grouping mechanism for interface objects. LayoutManagers provide means of positioning and sizing these objects. This class will be discussed in later sections.


Event Handling

Look at the screen in front of you. What is happening? Not much, probably. Your browser is sitting there waiting for you to click on an icon or for you to type something. In other words, it is waiting for an input event to take place. In pseudo-code you could think of a browser in the following terms:

while Input_Event != Quit loop
	
	read(Input_Event);            -- user types or click something
	perform_command(Input_Event); -- system executes corresponding command

end loop;
Of course, if you think about all of the things that a browser might do then this event loop will get quite complex. Here is some more detailed pseudo code:
while Input_Event != Quit loop
        
        read(Input_Event);            -- user types or click something

	switch Input_Event
	
		case Home_Icon: load_URL(Home); break;  -- click on the home icon

		case Back_Icon: load_URL(Previous_Page); break; -- click to go back

		case File_Menu: display(File_Menu.Options); break; -- display file options
			 
	/* etc etc etc */
 
end loop;
Where do these events come from? These events are passed to the AWT environment from the native peers, mentioned earlier. For instance, if the Java interface were running on a Macintosh then the event handling system within MacOS would first capture the event and then pass it on to AWT for further processing. Similarly, if the applet executed on a UNIX system running Motif then the X windows event handler would pass the event to AWT. All of this fits in with the
diagram shown earlier.

It is important that all event handler methods execute as quickly as possible. Otherwise the system may appear to hang - any subsequent input by the user may have no effect as the system handles previous events. Eventually, the relevant methods will complete and the system will appear to "catch up" in an extremely unpredictable manner.

Word of warning - the event model was one of the major changes that occured between AWT version 1.0 and 1.1. Although the fundamental concepts remain the same, the detailed implementation of these systems is different (1.0 uses an inheritance-based approach to event handling, 1.1 uses a cleaner delegation approach). We will focus on the 1.1 event mechanisms, full details about the 1.0 system are provided here.

Each event results in the creation of an Event object. These have the following attributes:

For example, the following code was taken from the button applet that we met earlier.
b1 = new Button();
b1.setLabel("Disable middle button");
b1.setActionCommand(DISABLE);
...
b1.addActionListener(this);
If the button b1 is selected then it will generate the DISABLE event. This event will then be passed to a special object called an action listener that is associated with "this" applet. The special action listener is shown below. The event e is identified using getActionCommand().
 public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
         
        if (command == DISABLE) { //They clicked "Disable middle button"
            b2.setEnabled(false);
            b1.setEnabled(false);
            b3.setEnabled(true);
        } else { //They clicked "Enable middle button"
            b2.setEnabled(true);
            b1.setEnabled(true);
            b3.setEnabled(false);
        }
    }
To summarise - in AWT 1.1 there are two basic concepts in event handling. A listener object is an instance of a class that listens for events that it has been told to accept. In the previous example, the ButtonDemo class extended the ActionListener interface. An event source is an object that can register listener objects and send them notification when those events occur (ie, an instance of the button class). In the previous example, the button class both generated and handled the users selection events.

There are eleven listener interfaces in the java.awt.Event package:

  1. ActionListener
  2. AdjustmentListener
  3. ComponentListener
  4. ContainerListener
  5. FocusListener
  6. ItemListener
  7. KeyListener
  8. MouseListener
  9. MouseMotionListener
  10. TextListener
  11. WindowListener

As we shall see, many interface components can be operated by either the mouse or the keyboard. For example, an OK button on a dialogue box can be selected or the user may simply press RETURN to confirm. In order for such keyboard input to be successful, the component must have the focus. In other words, the RETURN should not be sent to some other text component on the screen. Only one window and one component in that window can have the keyboard focus. Once a window has the focus, Component requestFocus() requests that a particular component gets the focus.


/*
* Simple warning program
*
* Author: Chris Johnson (johnson@dcs.gla.ac.uk)
* Last revision date: 11/10/98
*
* Produces a simple warning on the screen.   Illustrates the
* use of a frame and of a simple event handler in AWT 1.1
 */
 
import java.awt.*;
import java.awt.event.*;
 
public class CloseableSimpleWarning extends Frame implements
WindowListener
{
 
static private final int frame_height = 150;
static private final int frame_width = 250;
 
        public CloseableSimpleWarning()
        {
                //setBackground(Color.red);
                //setForeground(Color.black);
                setTitle("Warning");
                setSize(frame_width, frame_height);
                addWindowListener(this);
        }
 
        public void windowClosing (WindowEvent e)
        {
                System.exit(0);
        }
 
        public void windowClosed (WindowEvent e)
        {
                System.exit(0);
        }
 
        public void windowIconified (WindowEvent e)
        {
                System.exit(0);
        }
 
        public void windowDeiconified (WindowEvent e)
        {
                System.exit(0);
        }
 
                public void windowOpened (WindowEvent e)
        {
                System.exit(0);
        }
 
  public void windowActivated (WindowEvent e)
        {
                System.exit(0);
        }
 
        public void windowDeactivated (WindowEvent e)
        {
                System.exit(0);
        }
 
        public static void main(String [] args)
        {
                CloseableSimpleWarning f = new CloseableSimpleWarning();
 
                f.show();
        }
}
This code might look quite complicated because there are seven methods (windowClosing, windowClosed etc) that do the same thing - exit the system. We needed all of these methods because the windowListener interface expects you to implement all of them. In other words, the Java runtime environment needs to know what to do for all possible events that might be generated for a window and so it expects you to provide code to handle those events. Also, the previous program is not very interesting because ANY event generated for the window will cause the application to exit.

It is possible to simplify this task using adapter classes. These accept events for an object but will do nothing with them unless the programmer explicitly specifies an action:

class WindowCloser extends WindowAdapter
{
	void windowClosing(WindowEvent e)
	{
		System.exit(0);
	}
}
The following code implements this approach and will not cause the application to immediately exit. It is worth spending a few minutes figuring out why this behaviour is different from that of the previous example:
/*
* Simple warning program
*
* Author: Chris Johnson (johnson@dcs.gla.ac.uk)
* Last revision date: 5/1//99
*
* Produces a simple warning on the screen.   Illustrates the
* use of a frame and of a simple event handler in AWT 1.1
 */
 
import java.awt.*;
import java.awt.event.*;
 
 
 
 
public class CloseableSimpleWarning2 extends Frame
{
 
static private final int frame_height = 150;
static private final int frame_width = 250;
 
 
 
       public CloseableSimpleWarning2()
        {
 
         addWindowListener(new
          WindowAdapter()
          {
            public void windowClosing(WindowEvent e)
             {System.exit(0);}
          }
         );
 
 
                setBackground(Color.red);
                setForeground(Color.black);
                setTitle("Warning");
                setSize(frame_width, frame_height);
 
        }
 
 
        public static void main(String [] args)
        {
                CloseableSimpleWarning2 f = new CloseableSimpleWarning2();
 
                f.show();
        }
}

And now on to part three...


Copyright Chris Johnson, 2000.