Skip to content Skip to navigation

OpenStax-CNX

You are here: Home » Content » Java OOP: Event Handling in JDK 1.1, A First Look, Delegation Event Model

Navigation

Recently Viewed

This feature requires Javascript to be enabled.
 

Java OOP: Event Handling in JDK 1.1, A First Look, Delegation Event Model

Module by: R.G. (Dick) Baldwin. E-mail the author

Summary: This is the first module involving the use of the Delegation Event Model.

Preface

This module is one of a series of modules designed to teach you about Object-Oriented Programming (OOP) using Java.

(Editor's note: As you read this module, you will see that it was originally written in 1997. However, despite many improvements in Java since 1997, most of what was true in 1997 is still true in 2012.)

This module makes several references to my website, which is located at http://www.dickbaldwin.com/toc.htm . A copy of the original html version of this module is available here .

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.

Figures

Listings

Introduction

This module provides a description of the Delegation Event Model as defined in JDK 1.1 along with sample programs that illustrate some aspects of the model. I describe how the event model maps to the AWT API.

Much of this information was taken from the documentation released with the various versions of JDK 1.1, and is the intellectual property of Sun Microsystems. The material is being reproduced here for the sole purpose of assisting students in learning how to use the event model.

Design Goals of the JDK 1.1 Delegation Model

According to Sun, the primary design goals of the event model in the AWT are the following:

Note:

Design goals:
  • Simple and easy to learn
  • Support a clean separation between application and GUI code
  • Facilitate the creation of robust event handling code which is less error-prone (strong compile-time checking)
  • Flexible enough to enable varied application models for event flow and propagation
  • For visual tool builders, enable run-time discovery of both events that a component generates as well as the events it may observe
  • Support backward binary compatibility with the old model

It will be up to you to decide if they have met their goals.

Simplified Overview of the New Delegation Model

First, I will provide a simplified overview of the model including a sample program. Following that, I will embark on a detailed discussion of the model. Hopefully the simplified discussion and the sample program will help you to understand the material in the detailed discussion.

Also, the earlier module on callbacks should have given you considerable background to help you understand this material. If you are not familiar with the callback material, you should go back and review that material.

Event sources and listeners

Events are now organized into a hierarchy of event classes. The model makes use of event sources and event listeners .

An event source is an object that has the ability

  • to determine when an interesting event has occurred, and
  • to notify listener objects of the occurrence of the event.

Although you as the programmer establish the framework for such notification, the actual notification takes place automatically behind the scenes.

A listener object is an instance of a class (or instance of a subclass of a class) that

  • implements a specific listener interface.

A number of listener interfaces are defined where each interface declares the methods appropriate for a specific class of events. Thus, there is natural pairing of classes of events and interface definitions.

For example, there is a class of mouse events that includes most of the events normally associated with mouse action. There is a matching interface definition, which is used to define a listener class for those events (actually this is the one case where two interfaces are defined to match up with a single event class) .

Registration

A listener object can be registered on a source object to be notified of the occurrence of all events of the specific class for which the listener object is designed.

Once a listener object is registered to be notified of those events, the occurrence of an event defined by the specified class will automatically call the matching method in the listener object. The code in the body of the method is designed by the programmer to perform the desired action when the event occurs.

Multiple notification methods

Some event classes (such as the mouse events, for example) involve a number of different possible event types (notification methods) . A listener class that implements the matching interface for that event class must implement or define (provide a body for) all the methods declared in the interface.

Adapter classes

An intermediate set of classes, known as Adapter classes, is provided to prevent this from becoming burdensome. These Adapter classes implement the listener interfaces, and define the matching interface methods with empty methods.

A listener class can then be defined that extends the Adapter class instead of implementing the corresponding listener interface. With this approach, the listener class need only override those methods of interest since the requirement to define all of the interface methods has already been satisfied by the Adapter class.

An example

For example, in the sample program that follows, two different listener objects instantiated from two different listener classes are registered to receive all events involving the manipulation of a Frame object (opening, closing, minimizing, etc.) .

One of the listener classes implements the WindowListener interface and hence must define all six methods of that interface.

The other listener class extends the WindowAdapter class, which in turn implements the WindowListener interface. The WindowAdapter class defines all six methods as empty methods. Thus, this listener class can get by with overriding only two of the six methods of the interface.

Sample Program

This program named Event08 was designed for simplicity. In this program, the code in each of the methods is simple. In all cases but one, the code simply displays a message indicating that the method has been called. Obviously, in order for a program to be of much value, the body of code in the methods would have to be much more substantive, or at least would have to call other methods that are more substantive.

This program illustrates the use of Event Sources , Event Listeners , and Adapters in the Delegation Event Model .

Description

Briefly, this program instantiates an object that creates a user interface consisting of a simple Frame object. This object is an Event Source that notifies two different Event Listener objects of Window events.

One of the Listener objects implements the WindowListener interface and defines all of the methods declared in that interface. The other Listener object extends the Adapter class named WindowAdapter .

As explained earlier, the purpose of Adapter classes (as used in this context) is to implement the Listener interfaces and to define all of the methods with empty methods.

Classes that extend the Adapter classes can then selectively override only those methods of interest. This Listener object overrides only two of the methods.

(Note that this program does not terminate and return control to the operating system. You must forcefully terminate it.)

This program was originally tested using JDK 1.1.3 under Win95. More recently it was tested using JDK 1.7 under Windows Vista.

The output produced by running the program is presented later in this module.

Interesting Code Fragments

Listing 1 shows the main method of the controlling class that instantiates a Graphical User Interface (GUI) object. There are more compact (and more cryptic) ways to accomplish this objective, but for the time being, in order to achieve clarity, I will use this approach.

Listing 1: The main method for Event08.

public class Event08 {//controlling class
  public static void main(String[] args){
    GUI gui = new GUI();//instantiate a GUInterface object
  }//end main
}//end class Event08

The GUI class is rather long, so I will break it up and discuss it in parts.

This class is used

  • to instantiate and display a user interface object,
  • to instantiate two Listener objects, and
  • to register those two objects for notification whenever a Window event occurs.

The class begins by defining its own constructor. The first interesting code in the constructor is the code to instantiate an object of type Frame , set its size, and give it a title, as shown in Listing 2 .

Listing 2: Beginning of the constructor.

class GUI{
  public GUI(){//constructor
    //Create a new Frame object
    Frame displayWindow = new Frame();
    displayWindow.setSize(300,200);
    displayWindow.setTitle("Copyright 1997, R.G.Baldwin");

What is a Frame?

The JDK documentation describes a Frame as follows:

Note:

Description of a Frame:

A Frame is a top-level window with a title and a border. The default layout for a frame is BorderLayout . (We will learn more about layout managers later)

Frames are capable of generating the following types of window events:

  • WindowOpened
  • WindowClosing
  • WindowClosed
  • WindowIconified
  • WindowDeiconified
  • WindowActivated
  • WindowDeactivated.

Stated differently, a Frame object is the type of GUI object that we might refer to as a window or a form in a typical GUI environment.

Instantiate two Listener objects

Listing 3 instantiates two Listener objects that will process Window events.

The class definitions, named Wproc1 and Wproc2 , for these two classes will follow the discussion of the GUI class.

(Note that I am passing a reference to the Frame object to the constructor for one of these classes. There is a better (and more cryptic) way to achieve the same objective without the need to pass the reference. Again, since this program was designed for clarity, I am doing it the obvious way.)

Listing 3: Instantiate two Listener objects.


    WProc1 winProcCmd1 = new WProc1(displayWindow);
    WProc2 winProcCmd2 = new WProc2();

Register the listener objects

The code in Listing 4 is extremely important. This is the code by which we register the listener objects for notification of Window events where the Frame object named displayWindow is the source of the events.

Pay close attention to the syntax of these two statements, because you will be using this syntax often. In subsequent modules, we will dig deeper into the Delegation Event Model and I will teach you what is going on behind the scenes when you execute statements of this sort.

Listing 4: Register the listener objects .

    displayWindow.addWindowListener(winProcCmd1);
    displayWindow.addWindowListener(winProcCmd2);

Interpretation

The interpretation of the code in Listing 4 is that the two listener objects named winProcCmd1 and winProcCmd2 are added to a list of listener objects that are to be automatically notified

  • whenever an event of the WindowEvent class occurs
  • with respect to the Frame object named displayWindow .

These listener objects are notified by calling the methods in the objects that match the specific type of the event (open window, close window, closing window, minimize window, etc.) .

Make the Frame visible

We wrap up the definition of our GUI class with the statement shown in Listing 5 that causes the Frame object to become visible on the screen. Note that this statement also causes the windowActivated and windowOpened events to be generated. (Current jargon would say that those events are "fired".)

Listing 5: Make the Frame visible.

    displayWindow.setVisible(true);
  }//end constructor
}//end GUI class definition

Code for the Listener objects

At this point, we have examined the code that will create a Frame object and display it on the screen. Also we have examined the code that registers two Listener objects on the Frame object. However, at this point, the program cannot be compiled because the classes from which the two Listener objects are to be instantiated have not yet been defined. That will be our next assignment.

Beginning of the class named WProc1

Listing 6 begins the definition of the classes that can be used to instantiate Listener objects.

The first class definition that we will look at implements the WindowListener interface. This requires that all the methods declared in the interface be defined in this class. This class defines all of the methods. Each of the methods displays a descriptive message whenever it is called.

I will begin the discussion with the constructor as shown in Listing 6 .

Listing 6: Beginning of the class named WProc1.

class WProc1 implements WindowListener{
  Frame displayWindowRef;

  WProc1(Frame windowIn){//constructor
    this.displayWindowRef = windowIn;
  }//end constructor

(Note that the constructor for this class requires a reference to the Source object to be passed as a parameter. As mentioned earlier, this is not the preferred way to accomplish our objective, but it is the most straightforward and easy to understand. That is why I elected to use it here. The code in the constructor saves a reference to the Source object in an instance variable named displayWindowRef .)

Implementing the WindowListener interface

It is important to note that this class implements the WindowListener interface. This means that it must define all of the methods that are declared in that interface.

If you examine the complete program listing that is presented later, you will see that there is one method definition in this class definition for each of the methods that are declared in the WindowListener interface.

The definition of all the interface methods are very similar, so I am not going to show all of them here. However, I will show the one that requires the reference to the source object that was discussed above, which is the most complicated one of the set.

The windowClosing event handler

The methods that are declared in the listener interfaces are often referred to as event handler methods or event handlers for short. The windowClosing event handler method is shown in Listing 7 . As you can see, this method starts out by displaying a message. Then it calls the dispose method on the Frame object. That is the reason that a reference to the Frame object was required to be passed in as a parameter.

Calling the dispose method causes a WindowClosed event to be fired. (As far as I know, that is the only way to cause a WindowClosed event to be fired.)

Listing 7: The windowClosing event handler.

  public void windowClosing(WindowEvent e){
    System.out.println("WProc1 windowClosing test msg");
    displayWindowRef.dispose();//generate WindowClosed
  }//end windowClosing()

The class named WProc2

The class definition shown in Listing 8 does not implement the WindowListener interface. Instead, it extends the WindowAdapter class. Therefore, it can selectively override only those methods that are of interest.

In this case, only two of the methods of the WindowListener interface are overridden. These overridden methods display a message whenever they are called.

Listing 8: Definition for the class named WProc2.

class WProc2 extends WindowAdapter{

  public void windowIconified(WindowEvent e){
    System.out.println(
              "******** WProc2 windowIconified test msg");
  }//end windowIconified()

  public void windowDeiconified(WindowEvent e){
    System.out.println(
            "******** WProc2 windowDeiconified test msg");
  }//end windowDeiconified()

}//end class WProc2

Program output

Figure 1 shows a sample output from this program. The small Frame in the upper-left corner is the graphic Frame object. A command-line screen with text output is shown immediately below the Frame.

Figure 1: Program output.
Program output.
Missing image

The text output

The output from running this program for a variety of user actions is shown below. You should be able to correlate the messages shown in the output with the event handler methods discussed above and the user actions that caused those event handlers to be called.

Note:

Text output from Event08
This program was tested using JDK 1.1.3 under Win95.

When executed, this application places a simple empty
Frame object on the screen.

Starting the program produces the following output:
WProc1 windowActivated test msg
Wproc1 windowOpened test msg

Pressing the minimize button on the Frame produces the
following output:

WProc1 windowIconified test msg
******** WProc2 windowIconified test msg
WProc1 windowDeactivated test msg

Restoring the Frame after minimization produces the
following output:

WProc1 windowActivated test msg
WProc1 windowDeiconified test msg
******** WProc2 windowDeiconified test msg
WProc1 windowActivated test msg

Closing the Frame by pressing the X-icon in the upper
right of the Frame produces the following output.

WProc1 windowClosing test msg
WProc1 windowDeactivated test msg
WProc1 windowClosed test msg

Program Listing for Event08

A complete listing of the program is provided in Listing 9 . You can view the code that was not shown above in this listing.

Listing 9: Complete listing for Event08.

/*File Event08.java Copyright 1997, R.G.Baldwin
Rev 01/10/98

Illustrates the use of Event Sources, Event Listeners, and
Adapters in the Delegation Event Model.

Briefly, this application instantiates an object that
creates a user interface consisting of a simple Frame
object.  This object is an Event Source that notifies two
different Event Listener objects of Window events.

One of the Listener objects implements the WindowListener
interface and overrides all of the methods declared in
that interface.

The other Listener object extends the Adapter class named
WindowAdapter.  The purpose of Adapter classes is to
implement the  Listener interfaces and to define all of
the methods with empty methods.  Classes that extend the
Adapter classes can then selectively override only those
methods of interest.  This Listener object overrides only
two of the methods.

Note that this application does not terminate and return
control to the operating system.  You must forcefully
terminate it.

This program was tested using JDK 1.1.3 under Win95.

When executed, this application places a simple empty
Frame object on the screen.

Starting the program produces the following output:
WProc1 windowActivated test msg
Wproc1 windowOpened test msg

Pressing the minimize button on the Frame produces the
following output:

WProc1 windowIconified test msg
******** WProc2 windowIconified test msg
WProc1 windowDeactivated test msg

Restoring the Frame after minimization produces the
following output:

WProc1 windowActivated test msg
WProc1 windowDeiconified test msg
******** WProc2 windowDeiconified test msg
WProc1 windowActivated test msg

Closing the Frame by pressing the X-icon in the upper
right of the Frame produces the following output.

WProc1 windowClosing test msg
WProc1 windowDeactivated test msg
WProc1 windowClosed test msg
**********************************************************/

import java.awt.*;
import java.awt.event.*;

public class Event08 {
  public static void main(String[] args){
    GUI gui = new GUI();//instantiate a GUInterface object
  }//end main
}//end class Event08
//=======================================================//

//The following class is used to instantiate a user
// interface object, to instantiate two Listener objects,
// and to register those two objects for notification
// whenever a Window event occurs.
class GUI{
  public GUI(){//constructor
    //Create a new Frame object
    Frame displayWindow = new Frame();
    displayWindow.setSize(300,200);
    displayWindow.setTitle("Copyright 1997, R.G.Baldwin");

    //Instantiate two Listener objects that will process
    // Window events
    WProc1 winProcCmd1 = new WProc1(displayWindow);
    WProc2 winProcCmd2 = new WProc2();

    //Register the Listener objects for notification of
    // Window events. This object is the Event Source.
    displayWindow.addWindowListener(winProcCmd1);
    displayWindow.addWindowListener(winProcCmd2);

    //windowActivated and windowOpened test messages
    // are produced here
    displayWindow.setVisible(true);

  }//end constructor
}//end class GUI definition
//=======================================================//

//The following two classes can be used to instantiate
// Listener objects. Note that this class implements the
// WindowListener interface.  This requires that all the
// methods declared in the interface be overridden in this
// class. This class overrides all of the methods  and
// displays a descriptive message whenever one of the
// methods is called.
class WProc1 implements WindowListener{
  //used to save a reference to the Frame object
  Frame displayWindowRef;

  WProc1(Frame windowIn){//constructor
    // save ref to Frame object
    this.displayWindowRef = windowIn;
  }//end constructor

  public void windowClosed(WindowEvent e){
    System.out.println("WProc1 windowClosed test msg");
  }//end windowClosed()

  public void windowIconified(WindowEvent e){
    System.out.println("WProc1 windowIconified test msg");
  }//end windowIconified()

  public void windowOpened(WindowEvent e){
    System.out.println("WProc1 windowOpened test msg");
  }//end windowOpened()

  public void windowClosing(WindowEvent e){
    System.out.println("WProc1 windowClosing test msg");
    displayWindowRef.dispose();//generate WindowClosed
  }//end windowClosing()

  public void windowDeiconified(WindowEvent e){
    System.out.println(
                      "WProc1 windowDeiconified test msg");
  }//end windowDeiconified()

  public void windowActivated(WindowEvent e){
    System.out.println("WProc1 windowActivated test msg");
  }//end windowActivated()

  public void windowDeactivated(WindowEvent e){
    System.out.println(
                     "WProc1 windowDeactivated test msg");
  }//end windowDeactivated()
}//end class WProc1
//=======================================================//

//This and the previous class can be used to instantiate
// Listener objects. Note that this class extends an
// Adapter class that can be used to avoid the
// requirement to define all of the methods of the
// actual Listener class named WindowListener. This class
// overrides only two of the methods declared in the
// interface.  It displays a message whenever one of the
// methods is called.
class WProc2 extends WindowAdapter{

  public void windowIconified(WindowEvent e){
    System.out.println(
              "******** WProc2 windowIconified test msg");
  }//end windowIconified()

  public void windowDeiconified(WindowEvent e){
    System.out.println(
            "******** WProc2 windowDeiconified test msg");
  }//end windowDeiconified()

}//end class WProc2

More Detailed Overview of the Delegation Model

JDK 1.1 encapsulates events in a class hierarchy with the root class named java.util.EventObject .

The propagation of an event from a Source object to a Listener object involves calling a method on the Listener object and passing an object that contains encapsulated information about the event. Note that each event class may include more than one actual type of event (as determined by the methods declared in the listener interface) .

An event listener

A Listener object is an instance of a class that implements a specific EventListener interface extended from the generic java.util.EventListener .

An EventListener interface declares one or more methods that must be defined in the Listener class. Those methods are called by the event source in response to each specific event type handled by the interface.

The calling of these methods is the mechanism by which the Source notifies the Listener of the occurrence of an event of a specific type.

An event source

An Event Source is an object that "originates" or "fires" events by calling the methods of one or more Listener objects. The Source maintains a list containing a reference to all of the Listener objects that have registered to be notified of events of that class.

Registration of event listener objects

The programmer causes Listener objects to be added to this list using add (EventType) Listener method calls.

Placing references to Listener objects on the list is often referred to as registering specific Listeners to receive notification of specific events.

Notifying listener objects

Once the list is populated ( Listener objects are registered) , the Source object uses that list to notify each Listener of the occurrence of an event of the specified type without further effort on the part of the programmer.

Event sources and listeners

The Event Source is often a GUI component and the Listener is commonly an object of a class that implements the appropriate listener interface, but this is not a requirement. For example we will learn later how to cause a program to generate events without any physical involvement on the part of a user and a GUI component.

The Listener object could also be another AWT component that implements one or more Listener interfaces for the purpose of hooking GUI objects up to each other.

Event Hierarchy

As mentioned earlier, each specific event type is a member of a class of event types and these classes form a hierarchy of event classes.

Since a single event class may be used to represent more than one event type (i.e. MouseEvent represents mouse up, mouse down, mouse drag, mouse move, etc.) , some event classes may also contain an "id" (unique within that class) that maps to its specific event types.

Setter and getter methods

There are no public fields in the event classes. Rather the data in the event is encapsulated and available only through the use of appropriate setter and getter methods.

The setter methods only exist for attributes on an event that can be modified by a listener. If you continue with your studies in Java, you will learn that the setter and getter methods match a design pattern for Java Beans.

A concrete set of event classes is defined by the AWT. In addition, programmers may define their own event types by subclassing either java.util.EventObject or one of the AWT event classes.

Low-level vs. Semantic Events

The AWT provides two conceptual types of events:

  • low-level events
  • semantic events

Low-level events

A low-level event is one that represents a low-level input or window-system occurrence on a visual component on the screen. As of February 1997, JDK 1.1 defined the following low-level event classes:

Note:

Low-level event classes
  • java.util.EventObject
    • java.awt.AWTEvent
      • java.awt.event.ComponentEvent (component resized, moved,etc.)
        • java.awt.event.FocusEvent (component got focus, lost focus)
        • java.awt.event.InputEvent
          • java.awt.event.KeyEvent (component got key-press, key-release,etc.)
          • java.awt.event.MouseEvent (component got mouse-down, mouse-move,etc.)
        • java.awt.event.ContainerEvent
        • java.awt.event.WindowEvent

As indicated earlier, some of the event classes encompass several different event types. Generally, there are corresponding Listener interfaces for each of the event classes, and corresponding interface methods for each of the different event types in each event class.

Semantic events

Semantic events are defined at a higher-level to encapsulate the semantics of a user interface component's model. As of February 1997, the semantic event classes defined by the JDK 1.1 version of the AWT were as follows:

Note:

Semantic event classes
  • java.util.EventObject
    • java.awt.AWTEvent
      • java.awt.event.ActionEvent ("do a command")
      • java.awt.event.AdjustmentEvent ("value was adjusted")
      • java.awt.event.ItemEvent ("item state has changed")
      • java.awt.event.TextEvent ("the value of the text object changed")

A more general event type

The semantic events are not tied to specific screen-based component classes, but may apply across a set of components that implement a similar semantic model. For example, a Button object will fire an "action" event when it is pressed and a List object will fire an "action" event when an item is double-clicked.

Not tied to user actions

Even though the above discussion seems to tie these event classes to user actions on screen components (because that is the norm) , you need to remember that there is nothing to prevent you from having your code generate events of these types completely independent of such user actions. For example, you can easily cause an ActionEvent to be generated and attributed to some component whenever a software timer expires. We will learn how to do this sort of thing in subsequent modules.

Event Listeners

An EventListener interface will typically have a separate method for each distinct event type that the event class represents. For example, the FocusEventListener interface defines two methods, focusGained and focusLost , one for each event type that the FocusEvent class represents.

Low-level listener interfaces

As of February 1997, the low-level listener interfaces defined by the JDK 1.1 version of the AWT were as follows:

Note:

Low-level listener interfaces
  • java.util.EventListener
    • java.awt.event.ComponentListener
    • java.awt.event.ContainerListener
    • java.awt.event.FocusListener
    • java.awt.event.KeyListener
    • java.awt.event.MouseListener
    • java.awt.event.MouseMotionListener
    • java.awt.event.WindowListener

If you match this up with the previous list of low-level event classes, you will see that there is a listener interface defined for each of the "leaf" classes in the hierarchy of event classes. (In fact, there are two different listener interfaces defined for the MouseEvent class. This will be discussed further at the appropriate point in time.)

Semantic listener interfaces

As of February 1997, the semantic listener interfaces defined by the AWT were as follows:

Note:

Semantic event listener interfaces
  • java.util.EventListener
    • java.awt.event.ActionListener
    • java.awt.event.AdjustmentListener
    • java.awt.event.ItemListener
    • java.awt.event.TextListener

There is a one-to-one correspondence between semantic listener interfaces and semantic event classes.

Event Sources

All AWT event sources support a multicast model for listeners. This means that multiple listeners can be added and removed from a single source. In other words, notification of the occurrence of the same event can be sent to one or more listener objects.

According to JDK 1.1 documentation,

"The API makes no guarantees about the order in which the events are delivered to a set of registered listeners for a given event on a given source. Additionally, any event which allows its properties to be modified (via setXXX() methods) will be explicitly copied such that each listener receives a replica of the original event. If the order in which events are delivered to listeners is a factor for your program, you should chain the listeners off a single listener which is registered on the source (the fact that the event data is encapsulated in a single object makes propagating the event extremely simple)."

Low-level event sources

As before, a distinction is drawn between low-level and semantic events. The source for low-level events will often be one of the visual component classes ( Button , Scrollbar , etc.) because the event is bound to the actual component on the screen (but counterfeit events can be generated) .

As of February 1997, JDK 1.1 defined low-level listeners on the following components.

Note:

Low-level listener components
  • java.awt.Component
    • addComponentListener(ComponentListener l)
    • addFocusListener(FocusListener l)
    • addKeyListener(KeyListener l)
    • addMouseListener(MouseListener l)
    • addMouseMotionListener(MouseMotionListener l)
  • java.awt.Container
    • addContainerListener(ContainerListener l)
  • java.awt.Dialog
    • addWindowListener(WindowListener l)
  • java.awt.Frame
    • addWindowListener(WindowListener l)

Must take inheritance into account

To determine all of the specific event types that can be communicated from a source object to a listener object, you must take inheritance into account.

For example, as you will see in a sample program later in this module, a source object can detect mouse events on a Frame object and notify a MouseListener object of the occurrence of those events even though the above list does not show a MouseListener on a Frame . This is possible because a Frame object indirectly extends the Component class, and MouseListener is defined for the Component class.

Semantic event sources

As of February 1997, JDK 1.1 defined the following semantic listeners for AWT components:

Note:

Semantic listener components
  • java.awt.Button
    • addActionListener(ActionListener l)
  • java.awt.Choice (implements java.awt.ItemSelectable)
    • addItemListener(ItemListener l)
  • java.awt.Checkbox (implements java.awt.ItemSelectable)
    • addItemListener(ItemListener l)
  • java.awt.CheckboxMenuItem (implements java.awt.ItemSelectable)
    • addItemListener(ItemListener l)
  • java.awt.List (implements java.awt.ItemSelectable)
    • addActionListener(ActionListener l)
    • addItemListener(ItemListener l)
  • java.awt.MenuItem
    • addActionListener(ActionListener l)
  • java.awt.Scrollbar (implements java.awt.Adjustable)
    • addAdjustmentListener(AdjustmentListener l)
  • java.awt.TextArea
    • addTextListener(TextListener l)
  • java.awt.TextField
    • addActionListener(ActionListener l)
    • addTextListener(TextListener l)

The nature of semantic events

The nature of semantic event types can be inferred by noticing that in some cases, different types of components support the same type of semantic event. For example, four different types of components are identified in the above list that can register and service action events .

A single ActionEvent listener object could be registered to be notified of action events on one or more components of all of these types. Of course, it would then be necessary for the code in that event handler to determine which source was responsible for generating the event if such identification is important.

An important difference between low level events and semantic events has to do with where the classes that define those events plug into the class hierarchy. Low level events plug in further down the class hierarchy and inherit more methods that can be used to process the event object than is the case with semantic events.

Adapters

Many EventListener interfaces are designed to listen to multiple event classes. For example, the MouseListener listens to mouse-down, mouse-up, mouse-enter , etc. The MouseListener interface declares a method for each of these subtypes.

When you implement an interface, you are required to define all of the methods that are declared in the interface, even if you define them with empty methods. In some cases, the requirement to define all the methods declared in an interface can be burdensome.

For this reason (and possibly for some other reasons as well), the AWT provides a set of abstract adapter classes that match up with the defined interfaces. Each adapter class implements one interface and defines all of the methods declared by that interface as empty methods, thus satisfying the requirement to define all of the methods.

You can then define your listener classes by extending the adapter classes instead of implementing the listener interfaces.. This allows you the freedom to override only those methods of the interface that interest you.

Again, recall that the methods declared within an interface correspond to the individual event types contained within a corresponding event class, and the Source object notifies your Listener object of the occurrence of an event of a specific type by calling your interface method.

As of February 1997, the Adapter classes provided by the JDK 1.1 version of the AWT were as follows:

Note:

Adapter classes
  • java.awt.event.ComponentAdapter
  • java.awt.event.FocusAdapter
  • java.awt.event.KeyAdapter
  • java.awt.event.MouseAdapter
  • java.awt.event.MouseMotionAdapter
  • java.awt.event.WindowAdapter

Filtering for Performance

Since listeners are registered to handle specific event types, they are notified only of the occurrence of those event types and are not required to deal with event types for which they are not registered. That was not the case in JDK 1.0.2 where all events passed through a common set of event handler code whether those events were of interest or not.

This filtering of events should improve performance, especially with high frequency events, such as mouse-moves.

According to the JDK 1.1 documentation,

"All platforms should see some performance improvement from reduced event traffic, but the Solaris implementation should gain exceptional improvement since it's a network-based window system."

Another Sample Program

The previous program did not terminate when the user closed the window. The following program does terminate when the user closes the window by executing a System.exit(0) statement in the closing event handler..

The previous program implemented an Event Source object that notified two different Listener objects of the occurrence of an event in the Window class.

The following program implements an Event Source object that notifies one Listener object of the occurrence of an event in the Window class and notifies another Listener object of the occurrence of an event in the Mouse class.

This program implements a MouseListener interface on a Frame object, which is possible because the Frame class indirectly extends the Component class, and addMouseListener is defined on the Component class.

Program output

If you compile and execute this program, whenever you click the mouse inside the Frame , you should see the coordinates of the mouse pointer displayed above the mouse pointer as shown in Figure 2 below.

Figure 2: Screen output from Event09.
Screen output from Event09.
Missing image.

Event09 Interesting Code Fragments

The first interesting code fragment is the definition of the controlling class. The main method for this class instantiates a GUI object where all the real work is done. Listing 10 shows the class named Event09 including the main method.

Listing 10: Beginning of the class named Event09.

public class Event09 {
  public static void main(String[] args){
    GUI gui = new GUI();//instantiate a GUI
  }//end main
}//end class Event09

The paint and repaint methods

Various tutorial lessons on my website discuss the relationship between the paint method and the repaint method. If you are unfamiliar with that relationship, you may need to go back and review it.

In this program, we are going to override the paint method to make it possible for us to draw coordinate information on the screen.

In order to override the paint method, we need to extend the Frame class. By doing so, we can define our own version of the Frame class where we have the ability to override the paint method. Listing 11 extends Frame into MyFrame and overrides the paint method.

Listing 11: The class named MyFrame.

class MyFrame extends Frame{
  int clickX;
  int clickY;

  public void paint(Graphics g){
    g.drawString(
             "" + clickX + ", " + clickY, clickX, clickY);
  }//end paint()
}//end class MyFrame

Storing and using coordinate information

For future reference, note that this class contains a couple of instance variables that will be used to store X and Y coordinate information.

The overridden version of the paint method causes the coordinate values stored in clickX and clickY to be displayed in the client area of the Frame object at the location specified by the values of those two instance variables.

The drawString method

The drawString method requires three parameters. The first parameter is the string to draw on the screen. The next two parameters are the coordinate values in pixels where the string is to be drawn.

As is normally the case, coordinate values are specified relative to the upper left corner of the object being drawn on. The above overridden version of the drawString method converts the coordinate values to a String , and draws that string at the location specified by the coordinate values.

The class named GUI

As before, the GUI class is rather long. Therefore, I will break it up and discuss it in fragments.

The first fragment that I will discuss is the constructor that begins in Listing 12 . The important thing to note here is that we are not instantiating an object of type Frame . Instead, we are instantiating an object of type MyFrame that is our extended version of Frame .

Other than that, you should be familiar with the code in Listing 12 by now.

Listing 12: Beginning of the class named GUI.

class GUI {
  public GUI(){//constructor
    //Create a new Frame object, set size, title, etc.
    MyFrame displayWindow = new MyFrame();
    displayWindow.setSize(300,300);
    displayWindow.setTitle("Copyright 1997, R.G.Baldwin");
    displayWindow.setVisible(true);

Register two listener objects

Listing 13 uses standard syntax to instantiate and register two different Listener objects on the MyFrame object. The first is a WindowListener object that will terminate the program when the user closes the MyFrame object.

The second is a MouseListener object that will process mouse events on the MyFrame object.

It is typical to register listener objects as anonymous objects in those cases where a specific reference to the listener object is not otherwise needed. (Don't confuse anonymous objects with anonymous classes, which is the topic of a future module.)

Listing 13: Register two listener objects.

    displayWindow.addWindowListener(new WProc1());
    displayWindow.addMouseListener(
                             new MouseProc(displayWindow));
  }//end constructor
}//end class GUI definition

Listing 13 ends the definition of the GUI class. That brings us to the definition of Listener classes for the WindowListener and the MouseListener interfaces.

The MouseListener class

I will begin with the MouseListener class named MouseProc . This class extends the MouseAdapter class and does not directly implement the MouseListener interface. This saves us the trouble of having to create empty methods for event types that we are not interested in.

Objects of this class that are registered on the Source will be notified whenever a mousePressed() event occurs on the Source. This will cause the mousePressed method to be called. The mousePressed method will display the coordinates of the mouse pointer when the mouse is pressed on the source object.

The mousePressed method

When the mousePressed method is called, it receives a reference to an object of type MouseEvent as a parameter. Different types of events encapsulate different types of information in the object that is passed as a parameter to the event handler method. This particular object contains a variety of information, including the coordinates of the mouse pointer when the event occurred.

Extract and save mouse pointer coordinates

The code in the overridden mousePressed() method extracts that coordinate information from the object and stores it in the instance variables named clickX and clickY of the Source object.

Then it calls the repaint method on the source object, causing the source object to be repainted on the screen. This in turn causes the overridden paint method discussed earlier to be called, which displays the new coordinate information on the screen in the proper location.

The class named MouseProc

Listing 14 contain the definition of the MouseProc class, including the overridden mousePressed method.

Listing 14: The class named MouseProc.

class MouseProc extends MouseAdapter{
  MyFrame refToWin; //save a reference to the source here

  MouseProc(MyFrame inWin){//constructor
    refToWin = inWin;//save ref to window
  }//end constructor

  public void mousePressed(MouseEvent e){
    refToWin.clickX = e.getX();
    refToWin.clickY = e.getY();

    refToWin.repaint();
  }//end mousePressed()
}//end class MouseProc

The class named WProc1

Finally, we come to the class that is used to instantiate a listener object that terminates the program when the user closes the MyFrame object (see Listing 15 ) . You will be seeing this class over and over as you review the sample programs in upcoming modules.

Listing 15: The class named WProc1.

class WProc1 extends WindowAdapter{
  public void windowClosing(WindowEvent e){
    System.exit(0);
  }//end windowClosing()
}//end class WProc1

The WProc1 class extends the WindowAdapter class and overrides the method named windowClosing .

The windowClosing method is called when the user clicks the red X in the upper right corner of Figure 2 .That causes the static exit method of the System class to be called, which in turn causes the program to terminate.

Event09 Program Listing

A complete listing of the program named Event09 is provided in Listing 16 .

Listing 16: Complete listing of Event09.

/*File Event09.java Copyright 1997, R.G.Baldwin
This program is designed to be compiled under JDK 1.1

Illustrates the use of Event Sources, Event Listeners, and
Adapters in the Delegation Event Model.

This program instantiates a Listener object to process
mouse events. When a mouse press occurs in a Frame object,
the program gets the coordinates and then displays those
coordinates near the point of the mouse press.

This program was tested using JDK 1.1.3 under Win95.
**********************************************************/
import java.awt.*;
import java.awt.event.*;

public class Event09 {
  public static void main(String[] args){
    GUI gui = new GUI();//instantiate a GUI
  }//end main
}//end class Event09
//=======================================================//

//Subclass Frame in order to override the paint method.
class MyFrame extends Frame{
  int clickX;
  int clickY;

  public void paint(Graphics g){
    g.drawString(
             "" + clickX + ", " + clickY, clickX, clickY);
  }//end paint()
}//end class MyFrame
//=======================================================//

//The following class is used to instantiate a
// graphical user interface object.
class GUI {
  public GUI(){//constructor
    //Create a new Frame object, set size, title, etc.
    MyFrame displayWindow = new MyFrame();
    displayWindow.setSize(300,300);
    displayWindow.setTitle("Copyright 1997, R.G.Baldwin");
    displayWindow.setVisible(true);

    //Instantiate and register an anonymous Listener
    // object that will terminate the program when the
    // user closes the Frame.
    displayWindow.addWindowListener(new WProc1());

    //Instantiate and register an anonymous Listener
    // object that will process mouse events to determine
    // and display the coordinates when the user presses
    // the mouse button in the client area of the Frame.
    displayWindow.addMouseListener(
                             new MouseProc(displayWindow));
  }//end constructor
}//end class GUI definition
//=======================================================//

//This listener class monitors for mouse presses and
// displays the coordinates of the mouse pointer when the
// mouse is pressed on the source object. Note that this
// class extends is an adapter class.
class MouseProc extends MouseAdapter{
  MyFrame refToWin; //save a reference to the source here

  MouseProc(MyFrame inWin){//constructor
    refToWin = inWin;//save ref to window
  }//end constructor

  //Override the mousePressed method to determine and
  // display the coordinates when the mouse is pressed.
  public void mousePressed(MouseEvent e){
    //Get X and Y coordinates of mouse pointer and store
    // in an instance variable of the Frame object
    refToWin.clickX = e.getX();
    refToWin.clickY = e.getY();

    //Force the Frame object to be repainted in order to
    // display the coordinate information.
    refToWin.repaint();
  }//end mousePressed()
}//end class MouseProc
//=======================================================//

//The following listener is used to terminate the program
// when the user closes the frame.  Note that this class
// extends an adapter class.
class WProc1 extends WindowAdapter{
  public void windowClosing(WindowEvent e){
    System.exit(0);
  }//end windowClosing()
}//end class WProc1
//=======================================================//

Summary

In the simplest case, you can handle events as defined in JDK 1.1 with the following steps.

Step 1

Define a Listener class for a specific class of events by either implementing the listener interface that matches that class of events, or extending the corresponding adapter class.

Step 2

Define or override the interface methods in the Listener class, for each specific event type in the event class, to implement the desired behavior of the program upon occurrence of an event.

If you implement the listener interface, you must define all interface methods. If instead you extend the corresponding adapter class, you can override only those methods that tie to event types of interest.

Step 3

Write code that instantiates objects of the Source class and the Listener class and registers the listener object on the source object for notification of events generated by the source object.

You can use code such as the following for registration:

displayWindow. addMouseListener (mouseProcCmd);

In this code fragment,

  • displayWindow is a reference to the object that fires the event,
  • mouseProcCmd is the name of a reference to the listener object, and
  • addMouseListener is the method that registers the listener object to receive mouse events from the object referred to by displayWindow .

This statement will cause the object named mouseProcCmd to be notified of all events generated by displayWindow which are part of the class of mouse events.

The notification takes the form of calling a method in the mouseProcCmd object where there must be a corresponding method for each specific event type in the class of mouse events. (Some of those methods can be empty shells if you have no interest in some of the event types).

Comments

As mentioned earlier, this is the procedure for the simplest cases. It is possible to make the situation more complicated. For example, a single Source object can be required to notify two or more different Listener objects of the occurrence of an event of the same class on a single screen object.

The Source object can also be required to notify two or more different Listener objects of the occurrence of events of two different classes on a single screen object.

A single Listener object can be registered to receive notification of the occurrence of events of a given class on more than one source object. In that case, it is normally necessary for the code in the Listener object to crack open the event object to determine which screen object was responsible for the event (if it matters) .

Also, the JDK 1.1 documentation indicates that it is possible to have event-style communication between objects that are not screen objects. Subsequent modules will investigate a number of these possibilities.

Review

The original HTML version of this module contains a number of review questions with answers. If interested, you can take a look at those review questions .

Run the program

I encourage you to copy the code from Listing 9 and Listing 16 . Compile the code and execute it. Experiment with the code, making changes, and observing the results of your changes. Make certain that you can explain why your changes behave as they do.

Miscellaneous

This section contains a variety of miscellaneous information.

Note:

Housekeeping material
  • Module name: Java OOP: Event Handling in JDK 1.1, A First Look, Delegation Event Model
  • File: Java0080.htm
  • Published: 11/17/13

Note:

Disclaimers:

Financial : Although the Connexions site makes it possible for you to download a PDF file for this module at no charge, and also makes it possible for you to purchase a pre-printed version of the PDF file, you should be aware that some of the HTML elements in this module may not translate well into PDF.

I also want you to know that, I receive no financial compensation from the Connexions website even if you purchase the PDF version of the module.

In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle books, and placed them for sale on Amazon.com showing me as the author. I neither receive compensation for those sales nor do I know who does receive compensation. If you purchase such a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it was made and published without my prior knowledge.

Affiliation : I am a professor of Computer Information Technology at Austin Community College in Austin, TX.

-end-

Content actions

Download module as:

Add module to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens

Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks