CSCI A202 - Introduction to Programming (II)

There are four steps to creating a GUI:

  1. Create the components
  2. Add the components to a container
  3. Arrange, or lay out, the components within their container
  4. Handle the events generated by the components
This lecture gives an overview of the last step.

Lecture 26: Java 1.1's event-driven programming model.

Unlike procedural programs, window-based programs require an event-driven model in which the underlying environment tells your program when something happens. (For example, when the user clicks on the mouse, the environment (Windows '95, NT, Unix, MacOS, etc.) generates an event that it sends to the program. The program must then figure out what the mouse click means, and act accordingly.)

Java 1.1 implements a "delegation" model, in which events are distributed only to objects that have been registered to receive the event. In Java 1.1 event model, all event functionality is contained in a new (compared to the 1.0 version of Java) package, java.awt.event. Within this package, subclasses of the abstract class AWTEvent represent different kinds of events.

The package also includes a number of EventListener interfaces that are implemented by classes that want to receive different kinds of events; they define the methods that are called when events of the appropriate type occur. A number of adapter classes are also included; they correspond to the EventListener interfaces and provide null implementations of the methods in the corresponding listener. (These adapter classes aren't essential but provide a convenient shortcut for developers).

You want to see the big picture first? (It's always useful to have the big picture handy). Look up AWTEvent while you are at it. You will see a hierarchy like this:

class java.util.EventObject (implements 
  +--- abstract class java.awt.AWTEvent 
  |      |
  |      +-- class java.awt.event.ActionEvent 
  |      +-- class java.awt.event.AdjustmentEvent 
  |      +-- class java.awt.event.ComponentEvent 
  |      |     | 
  |      |     +-- class java.awt.event.ContainerEvent 
  |      |     +-- class java.awt.event.FocusEvent 
  |      |     +-- abstract class java.awt.event.InputEvent 
  |      |     |     | 
  |      |     |     +-- class java.awt.event.KeyEvent 
  |      |     |     +-- class java.awt.event.MouseEvent 
  |      |     | 
  |      |     +-- class java.awt.event.PaintEvent 
  |      |     +-- class java.awt.event.WindowEvent 
  |      |
  |      +-- class java.awt.event.ItemEvent 
  |      +-- class java.awt.event.TextEvent 
This is the hierarchy of Java events, which will be discussed below.

The old and new event models are incompatible. Although Java 1.1 supports them both, you should not use both models in the same program.

The Java 1.1 Event Model

This newer model requires objects to be registered to receive events. Then, only those objects that are registered are told when the event actually happens.

This new model is called delegation: it implements an observer - observable pattern with events. It is important in many respects. Any object, not just Components, can receive events.

The delegation model has several other ramifications but the bottom line is that an event will be delivered to every object that is registered as a listener for that event, regardless of what other objects do with the event. Any listener can mark an event "consumed," so it will be ignored by the peer or (if they care) other listeners. Finally, the 1.1 event model includes the idea of an event queue. To see all events you can peek into the system's event queue by using the EventQueue class.

In Java 1.1

Objects that are interested in an event are called listeners.

Each event type corresponds to a listener interface (that specifies the methods that are called when the event occurs), as detalied below (all classes and interfaces are from java.awt.event unless explicitly mentioned otherwise):

java.awt.AWTEvent                 java.util.EventListener 
   |                                                   |
   +-- ActionEvent .............. ActionListener ------+
   +-- AdjustmentEvent .......... AdjustmentListener --+
   +-- ComponentEvent ........... ComponentListener ---+
   |     +-- ContainerEvent ..... ContainerListener ---+
   |     +-- FocusEvent ......... FocusListener -------+
   |     +-- InputEvent                                |
   |     |     +-- KeyEvent ..... KeyListener ---------+
   |     |     +-- MouseEvent ... MouseListener -------+ 
   |     |                :...... MouseMotionListener -+
   |     +-- PaintEvent                                |
   |     +-- WindowEvent ........ WindowListener ------+
   +--- ItemEvent ............... ItemListener --------+
   +-- TextEvent ................ TextListener --------+ 
(Interfaces are in italics. Interfaces for which there is an adapter class are also underlined).

To receive an event, an object

  1. must implement the appropriate listener interface
  2. and must be registered with the event's source.
Registration with an event's source is done through a call to an "add listener" method (of the component that generates the event).

Here's an example, followed by an annotated version of the diagram in which

information is included.

The example first, in slow motion:

  1. A TextField object
    Textfield inputBuffer = new TextField(); 
    can generate action events (which in Java 1.1 are of the class ActionEvent).

  2. Let's say that we have an object myHandler
    myHandler = new TextActionHandler(); 
    that is interested in receiving action events from inputBuffer.

  3. This means that our object must implement the ActionListener interface, and this in turn means that it must include an actionPerformed() method, which is called when an action event occurs.

  4. Now we need to register our object's interest in actions generated by inputBuffer:

  5. Once our object has been registered,
    will be called whenever a user does anything in the textfield that generates an action event (like, for example, typing a carriage return).

Here's the entire text that may appear in a constructor:
TextField inputBuffer; 
public AWTExample() {
  inputBuffer = new TextField(); 
  myHandler = new TextActionHandler(); 
  inputBuffer.addActionListener(myHandler); // register handler
                                            // for buffer's events
  add(inputBuffer); // add the input buffer to the display 
Of course, there are many other kinds of events.

Here's the event hierarchy again together with the associated listener interfaces and the components that produce those events.

java.awt.AWTEvent                 java.util.EventListener 
   |                                                   |
   +-- ActionEvent .............. ActionListener ------+
   |   Button                 [1]                      |
   |   List                   [2]                      |
   |   MenuItem               [3]                      |
   |   TextField              [4]                      |
   +-- AdjustmentEvent .......... AdjustmentListener --+
   |   Scrollbar              [5]                      |
   +-- ComponentEvent ........... ComponentListener ---+
   |   Component              [6]                      |
   |     +-- ContainerEvent ..... ContainerListener ---+
   |     |   Container        [7]                      |
   |     +-- FocusEvent ......... FocusListener -------+
   |     |   Component        [8]                      |
   |     +-- InputEvent                                |
   |     |     +-- KeyEvent ..... KeyListener ---------+
   |     |     |   Component  [9]                      |
   |     |     +-- MouseEvent ... MouseListener -------+ 
   |     |         Component [10] MouseMotionListener -+
   |     +-- PaintEvent                                |
   |     +-- WindowEvent ........ WindowListener ------+
   |         Window          [11]                      |
   +--- ItemEvent ............... ItemListener --------+
   |    Checkbox             [12]                      |
   |    CheckboxMenuItem     [13]                      |
   |    Choice               [14]                      | 
   |    List                 [15]                      |
   +--- TextEvent ................ TextListener -------+ 
        TextComponent        [16] 
You can read the table above this way too:

Component Events Generated Meaning
Button [1] ActionEvent User clicked on the button.
Checkbox [12] ItemEvent User selected or deselected an item.
CheckboxMenuItem [13] ItemEvent User selected or deselected an item.
Choice [14] ItemEvent User selected or deselected an item.
Component [6] ComponentEvent Component moved, resized, hidden, or shown.
[8] FocusEvent Component gained or lost focus.
[9] KeyEvent User pressed or released key.
[10] MouseEvent User pressed or released mouse button, mouse entered or exited component, or user moved or dragged mouse.
List [2] ActionEvent User-double clicked on list item.
[15] ItemEvent User selected or deselected an item.
MenuItem [3] ActionEvent User selected a menu item.
Scrollbar [5] AdjustmentEvent User moved the scrollbar.
TextComponent [16] TextEvent User changed text.
TextField [4] ActionEvent User finished editing text.
Window [11] WindowEvent Window opened, closed, iconified, deiconified, or close requested.
Here's now more detail on the listener interfaces:

  Event Class       Listener Interface    Listener Methods 

  ActionEvent       ActionListener        actionPerformed()
  AdjustmentEvent   AdjustmentListener    adjustmentValueChanged()
  ComponentEvent    ComponentListener     componentHidden()

  ContainerEvent    ContainerListener     componentAdded()

  FocusEvent        FocusListener         focusGained()

  ItemEvent         ItemListener          itemStateChanged()
  KeyEvent          KeyListener           keyPressed()

  MouseEvent        MouseListener         mouseClicked()
                    MouseMotionListener   mouseDragged()

  TextEvent         TextListener          textValueChanged()
  WindowEvent       WindowListener        windowActivated()