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:
Object | Component | -------------------------------------------------------------------------------- Canvas Scrollbar Container Button Checkbox TextComponent Label List Choice | | ----------- ----------- Panel Window TextArea TextField | ---------- Dialog Frame | FileDialogThe 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 | FileDialogNote 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); } public static void main (String[] args){ Frame f= new SimpleWarning(); f.setTitle("Warning"); f.resize(frame_width, frame_height); 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:
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); } }The development of a graphical user interface in AWT, typically, depends upon the programmer overriding methods associated with particular components when an event occurs. For instance, the setSize method is invoked in response to resize events for particular components. These events are generated whenever the user attempts to resize that component. A programmer might override this method, for instance to warn the user that it is not possible to resize that particular component.
Each event is first passed to the handleEvent method. This, in turn, calls the associated methods from the previous list. The Component class provides a number of methods, such as setSize in the previous example, that are called in response to particular events. The associated events appear in parentheses after the method:
Only Button, Checkbox,Choice, List, MenuItem, and TextField produce action() events. They do so when the user indicates somehow that the control should perform an action. For example, when the user clicks a button, an action event is generated. By implementing the action() method, you can react to user actions on controls without worrying about the low-level events, such as key presses and mouse clicks, that caused the action. Here is an example from a simple program:
public boolean action(Event e, Object what){ /* * The what parameter varies depending on the object associated with * the event, in the case of a button it provides the textual label (String) * that is displayed on the button. */ if (e.target == quitButton) { System.exit(0); } return true;}
Each of the previous methods returns a Boolean value to indicate whether or not the method successfully handled the event. If False is returned then the event is handed up to components higher in the hierarchy. Again, this was illustrated in the previous example.
The following example shows how the handleEvent method can be overridden in order to close the warning window that was generated in the Frame example from the previous section. Here is the output from this application viewed on a Macintosh. What are the problems with the design of this warning?
/* * 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.0 * Based on an example by Judy Bishop, JavaGentely, * Addison Wesley 1998, p. 310 */ /* * 1.0 version. */ import java.awt.*; public class SimpleWarning extends Frame { static private final int horigap = 15; static private final int vertigap = 10; public SimpleWarning (String[] message, int n) { setBackground(Color.red); setForeground(Color.black); setLayout(new FlowLayout(FlowLayout.CENTER, horigap, vertigap)); for (int i=0; n>i; i++) add (new Label(message[i])); } public boolean handleEvent(Event e){ if (e.id == Event.WINDOW_DESTROY) { System.exit(0); } return super.handleEvent(e); } public static void main (String[] args){ String[] message = { "WARNING", "Something has gone badly wrong", "I'd go home..." }; Frame f= new SimpleWarning(message, 3); f.setTitle("Warning"); f.resize(240, 100); f.show(true); } }The following example extends this to include a quit button. Here we respond to any events involving the quitButton within the handleEvent method. This could also have been done by overriding the action() method mentioned above.
/* * Warning program with a Cancel button * * 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.0 * Based on an example by Judy Bishop */ /* * 1.0 version. */ import java.awt.*; public class ButtonWarning extends Frame { static private final int horigap = 15; static private final int vertigap = 10; private Button quitButton; public ButtonWarning (String[] message, int n) { setBackground(Color.white); setForeground(Color.black); setLayout(new FlowLayout(FlowLayout.CENTER, horigap, vertigap)); for (int i=0; n>i; i++) add (new Label(message[i])); quitButton = new Button("Quit"); add(quitButton); } public boolean handleEvent(Event e){ if (e.id == Event.WINDOW_DESTROY || e.target == quitButtton) { System.exit(0); } return super.handleEvent(e); } public static void main (String[] args){ String[] message = { "WARNING", "Something has gone badly wrong", "I'd go home..." }; Frame f= new ButtonWarning(message, 3); f.setTitle("Warning"); f.resize(240, 100); f.show(true); } }If you run this program you should notice that the handleEvent() method now exits the system when any event is received on the quitButton. This is not exactly what is required because an event will be generated whenever the mouse moves over this button and not only when the button is selected. A useful exercise would be to write a handler so that the system only quits when the user releases the mouse over the quitButton. Have a go and then look at this solution to the problem.