Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

Event Handling in JDK 1.1, A First Look, Delegation Event Model

Java Programming, Lesson # 80, Revised 02/13/98.

Preface

Students in Prof. Baldwin's Intermediate Java Programming classes at ACC are responsible for knowing and understanding all of the material in this lesson.

Introduction

This is the first lesson in this series on the Delegation Event Model as defined in JDK 1.1.

There are many significant changes between JDK 1.0.2 and JDK 1.1. Perhaps the area of greatest change is in the event handling model. The old model has been completely replaced by a new model. There is little or no resemblance between the Delegation Model used in JDK 1.1 and the Inheritance Model used in JDK 1.0.2.

This lesson will provide a description of the new model along with sample programs that illustrate some aspects of the new model.

Subsequent lessons will deal with the new model in more detail, providing more complex sample programs.

In this and the following sections, we will describe how the new model maps to the AWT API. No attempt will be made to discuss the rationale for the change. You are referred to the JavaSoft site for discussions of that sort.

Please note that 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 new event model.

A Quick Review of the 1.0 Event Model

The model for event processing in version 1.0 of the AWT is based on inheritance. In order for a program to catch and process GUI events, it must subclass GUI components and override either action() or handleEvent() methods.

Returning "true" from one of these methods consumes the event so it is not processed further. Otherwise the event is propagated sequentially up the GUI hierarchy until either it is consumed or the root of the hierarchy is reached. The result of this model is that programs have essentially two choices for structuring their event-handling code:

Although I indicated above that I would not discuss the rationale for making the change, there is one aspect of the change that is so compelling as to merit discussion here.

In the inheritance model from version 1.0, there is no filtering of events. Events are always delivered to components regardless of whether the components actually handle them or not. This is a general performance problem, particularly with high-frequency events such as mouse moves. Sun predicts that all systems should see performance improvement as a result of this change with the most improvement being enjoyed by Solaris systems.

Design Goals of the JDK 1.1 Delegation Model

According to Sun, the primary design goals of the new model in the AWT are the following:
 
  • 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, we will provide an simplified overview of the new model including a sample program. Following that, we will embark on a detailed discussion of the new model. Hopefully the simplified discussion and the sample program will help you to understand the material in the detailed discussion.

Also, the previous lesson on callbacks should have given you considerable background to help you understand this material. If you are not familiar with the material in those lessons, you should go back and review that material.

Events are now organized into a hierarchy of event classes.

The new 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 and 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).

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 invoke 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.

Some event classes (such as the mouse events, for example) involve a number of different possible event types. A listener class which implements the matching interface for that event class must implement or define (provide a body for) all the methods declared in the interface. To prevent this from being burdensome, an intermediate set of classes, known as Adapter classes, is provided.

These Adapter classes implement the listener interfaces, and define the matching interface methods with empty methods. A listener class can then be defined which extends the Adapter class instead of implementing the interface. When this is done, 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.

For example, in the sample program which 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 was designed for simplicity. In this program, the code body in each of the methods is simple. In all cases but one, the code simply displays a message indicating that the method has been invoked. 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 invoke other methods that are more substantive.

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

Briefly, this application instantiates an object which creates a user interface consisting of a simple Frame object. This object is an Event Source which 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. (Adapter classes are viewed in a broader context in the advanced lessons on the Reflection API.)

Classes which 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.

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

Interesting Code Fragments

The first interesting code fragment is the main() method of the controlling class which 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, we will use this approach.
 
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 we will break it up and discuss it in parts.

This class is used

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.
 
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");
According to the JDK documentation:
 
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.

Next we will instantiate 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 we are 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, we are doing it the obvious way. Another program later in the lesson shows the preferred way.
 
    WProc1 winProcCmd1 = new WProc1(displayWindow);
    WProc2 winProcCmd2 = new WProc2();
The next code fragment 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 lessons, we will dig deeper into the Delegation Event Model and teach you what is going on behind the scenes when you execute statements of this sort.
 
    displayWindow.addWindowListener(winProcCmd1);
    displayWindow.addWindowListener(winProcCmd2);
The interpretation of this code fragment 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 invoking the methods in the objects which match the specific type of the event (open window, close window, closing window, minimize window, etc.).

We wrap up the definition of our GUI class with a statement which causes the Frame object to become visible on the screen. Note that this statement also causes the windowActivated and windowOpened events to be generated.
 
    displayWindow.setVisible(true);
  }//end constructor
}//end GUI class definition
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 registered 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.

The code fragments that follow describe the two 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 invoked.

We will begin our discussion with the 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 we elected to use it here. The code in the constructor saves a reference to the Source object in an instance variable named displayWindowRef.
 
class WProc1 implements WindowListener{
  Frame displayWindowRef;
  
  WProc1(Frame windowIn){//constructor
    this.displayWindowRef = windowIn;
  }//end constructor
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 them all here. I will show the one that requires the reference to the source object that was discussed above.

This is our definition of the windowClosing() event handler method. As you can see, this method starts out by displaying a message. However, it then invokes the dispose() method on the Frame object, and that is the reason that a reference to the Frame object was required to be passed in as a parameter.

Invoking the dispose() method causes a WindowClosed event to be generated.
 
  public void windowClosing(WindowEvent e){
    System.out.println("WProc1 windowClosing test msg");
    displayWindowRef.dispose();//generate WindowClosed
  }//end windowClosing()
The next class does not implement the WindowListener interface, but rather extends the WindowAdapter class instead. Therefore, it can selectively override only those methods 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 invoked.
 
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
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 invoked.
 
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
A complete listing of the program is provided in the next section.

Note that as discussed earlier, an improved version of this program is presented at the end of this lesson. The improved version does not require the passing of a Frame object reference to the constructor for the WindowListener object in order to make it possible for the WindowListener object to reference the Frame object. You should become familiar with the methodology used in the improved version as well as the methodology used in this following version.

Program Listing

/*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 which 
creates a user interface consisting of a simple Frame 
object.  This object is an Event Source which 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 which 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 which 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 invoked.
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 which 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 invoked.
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 invoking a method on the Listener object and passing an object which contains encapsulated information about the event. Note that each event class may include more than one actual type of event.

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 which must be defined in the Listener class, and which are invoked by the event source in response to each specific event type handled by the interface.

The invoking 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 is an object which "originates" or "fires" events by invoking 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.

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.

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.

The Event Source is often a GUI component and the Listener is commonly an object of a class which 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 which implements one or more Listener interfaces for the purpose of hooking GUI objects up to each other.

Event Hierarchy

As mentioned earlier, events in JDK 1.1 are not represented by a single Event class with numeric identifications as in JDK 1.0.2. Rather, 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) which maps to its specific event types.

There are no public fields in the new event classes. Rather the data in the event is encapsulated and available only through the use of appropriate set...() and get...() methods.

The set 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 set and get 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. 
A low-level event is one which 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:
 
  • 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 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:
 
  • 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") 
The semantic events are not tied to specific screen-based component classes, but may apply across a set of components which 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.

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 lessons.

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.

As of February 1997, the low-level listener interfaces defined by the JDK 1.1 version of the AWT were as follows:
 
  • 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.)

The semantic listener interfaces defined by the AWT are as follows:
 
  • 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)."
(An example program showing how you might do the type of chaining described above is presented in the Advanced tutorial in the lessons on the Reflection API.)

As before, a distinction is drawn between low-level and semantic events. The source for low-level events will normally 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.
 
  • 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) 
It is important to note that 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 lesson, 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.

As of February 1997, JDK 1.1 defined the following semantic listeners for AWT 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 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.

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 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 which 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 which 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 invoking your interface method.

As of February 1997, the Adapter classes provided by the JDK 1.1 version of the AWT were as follows:
 
  • 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 which notified two different Listener objects of the occurrence of an event in the Window class.

The following program implements an Event Source object which 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.

As mentioned earlier, 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.

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.

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.
 
public class Event09 {
  public static void main(String[] args){
    GUI gui = new GUI();//instantiate a GUI
  }//end main
}//end class Event09
Early in the Introductory course, in the lesson that introduced Applets, we discussed the relationship between the paint() method and the repaint() method. If you have forgotten that discussion, you will 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. We also discussed drawing on the screen in the lesson on Applets, so you might need to refer back to that also. (We will have a lot more to say about drawing on the screen when we get into graphics later.)

In order to override the paint() method, we need to extend the Frame class to produce our own version of the Frame class where we have the ability to override the paint() method. The following code fragment extends Frame into MyFrame and overrides 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
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.

If you review the particulars of the drawString() method, you will see that it needs 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-hand 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.

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

The first fragment that we will discuss is the constructor. The important thing to note here is that we are not instantiating an object of type Frame. Rather, we are instantiating an object of type MyFrame which is our extended version of Frame.

Other than that, this is pretty standard stuff by now.
 
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);
The next code fragment 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.
 
    displayWindow.addWindowListener(new WProc1());
    displayWindow.addMouseListener(
                             new MouseProc(displayWindow));
  }//end constructor
}//end class GUI definition
As you can see above, that ends the definition of the GUI class. That brings us to the definition of Listener classes for the WindowListener and the MouseListener interfaces.

We will begin with the MouseListener class. Note that 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 invoked which will display the coordinates of the mouse pointer when the mouse is pressed on the source object. Note that this class extends an adapter class.

When the mousePressed() method is invoked, it receives 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. This particular object contains a variety of information, including the coordinates of the mouse pointer when the event occurred.

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 invokes the repaint() method on the source object, causing the source object to be repainted on the screen. This causes the overridden paint() method discussed earlier to be invoked, which displays the new coordinate information on the screen in the proper location.
 
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
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. You will be seeing this class over and over as you review the sample programs in upcoming lessons.
 
class WProc1 extends WindowAdapter{
  public void windowClosing(WindowEvent e){
    System.exit(0);
  }//end windowClosing()
}//end class WProc1
Note that an improved version of this program is presented at the end of this lesson. The improved version does not require the passing a MyFrame object reference to the constructor for the WindowListener object. You should become familiar with the methodology used in the improved version as well as the methodology used in the following version.

Event09 Program Listing

/*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 which 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

The Delegation Event Model used in JDK 1.1 is radically different from the Inheritance Event Model used in JDK 1.0.2.

In the simplest case, you can handle low-level events in JDK 1.1 with the following steps. (Semantic events will be discussed in a subsequent lesson).

Step 1

Define a Listener class for a specific class of events by either implementing the listener interface which 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 which tie to event types of interest.

Step 3

Define a class which instantiates an object of the Source class and the Listener class and registers the listener object on the source object for notification of the occurrence of events generated by the source object, using code such as the following:
 
    displayWindow.addMouseListener(mouseProcCmd);
In this code fragment, 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 invoking a method in the mouseProcCmd object where there must be a corresponding method for each specific event type in the class of mouse events (but 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, an earlier sample program required a Source object to notify two different Listener objects of the occurrence of an event of the same class on a single screen object.

Another sample program required the Source object to notify two different Listener objects of the occurrence of events of two different classes on a single screen object.

It is also possible to cause a single Listener object to 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 lessons will investigate a number of these possibilities.

Review

Q - Write a Java application that will cause a single Frame object to appear on the screen with a width of 300 pixels and a height of 100 pixels.

Make your name appear in the banner at the top of the object.

Implement the WindowListener interface to cause an appropriate message to appear on the screen whenever you perform any of the actions associated with the methods declared in that interface.

Make certain that your application terminates and returns control to the operating system when the user clicks on the "close" button in the upper right-hand corner of the object.

Performing various operations on the object should produce screen outputs similar to the following:
 
WindowProcessor windowIconified test msg 
WindowProcessor windowDeactivated test msg 
WindowProcessor windowActivated test msg 
WindowProcessor windowDeiconified test msg 
WindowProcessor windowActivated test msg 
WindowProcessor windowClosing test msg
A - See program below.
 
/*File SampProg117.java from lesson 80
Copyright 1997, R.G.Baldwin
*/

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

public class SampProg117 {
  public static void main(String[] args){
    //instantiate a Graphical User Interface object
    GUI gui = new GUI();
  }//end main
}//end class SampProg117
//---------------------------------------------------------
class GUI{
  public GUI(){//constructor
    //create a new Frame object
    Frame displayWindow = new Frame();
    displayWindow.setSize(300,100);
    displayWindow.setTitle("Copyright 1997, R.G.Baldwin");
    displayWindow.setVisible(true);
    
    //Instantiate and Register a Listener object for 
    // notification of Window events. 
    displayWindow.addWindowListener(
      new WindowProcessor(displayWindow));

  }//end constructor
}//end class GUI definition
//----------------------------------------------------------
class WindowProcessor implements WindowListener{
  Frame displayWindowRef;
  
  WindowProcessor(Frame windowIn){//constructor 
    //save ref to the Frame object passed as a parameter
    this.displayWindowRef = windowIn;
  }//end constructor

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

  public void windowClosing(WindowEvent e){
    System.out.println(
      "WindowProcessor windowClosing test msg");
    displayWindowRef.setVisible(false); //hide the window
    System.exit(0);
  }//end windowClosing()

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

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

  public void windowDeactivated(WindowEvent e){
    System.out.println(
      "WindowProcessor windowDeactivated test msg");
  }//end windowDeactivated()
}//end class WindowProcessor
Q - Write a Java application that will cause a single Frame object to appear on the screen with a width of 300 pixels and a height of 100 pixels.

Make your name appear in the banner at the top of the object.

Make certain that your application terminates and returns control to the operating system when the user clicks on the "close" button in the upper right-hand corner of the object.

Extend the WindowAdapter class to cause the three messages shown below to appear on the screen when the object is minimized, restored, and closed.
 
WindowProcessor windowIconified test msg 
WindowProcessor windowDeiconified test msg 
WindowProcessor windowClosing test msg
A - See program below.
 
/*File SampProg118.java from lesson 80
Copyright 1997, R.G.Baldwin
*/

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

public class SampProg118 {
  public static void main(String[] args){
    //instantiate a Graphical User Interface object
    GUI gui = new GUI();
  }//end main
}//end class SampProg118
//---------------------------------------------------------
class GUI{
  public GUI(){//constructor
    //create a new Frame object
    Frame displayWindow = new Frame();
    displayWindow.setSize(300,100);
    displayWindow.setTitle("Copyright 1997, R.G.Baldwin");
    displayWindow.setVisible(true);
    
    //Instantiate and Register a Listener object for 
    // notification of Window events. 
    displayWindow.addWindowListener(
      new WindowProcessor());

  }//end constructor
}//end class GUI definition
//----------------------------------------------------------
class WindowProcessor extends WindowAdapter{
  
  public void windowIconified(WindowEvent e){
    System.out.println(
      "WindowProcessor windowIconified test msg");  
  }//end windowIconified()
  
  public void windowClosing(WindowEvent e){
    System.out.println(
      "WindowProcessor windowClosing test msg");
    System.exit(0);
  }//end windowClosing()

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

}//end class WindowProcessor
Q - Write a Java application that will cause a single Frame object to appear on the screen with a width of 300 pixels and a height of 300 pixels.

Make your name appear in the banner at the top of the object.

Make certain that your application terminates and returns control to the operating system when the user clicks on the "close" button in the upper right-hand corner of the object.

Implement a Listener interface to cause the application to terminate when the user presses the close button.

Extend an adapter class to process mouse events. When a mouse press occurs in the Frame object, the program displays the mouse coordinates near the point of the mouse press.

A - See program below.
 
/*File SampProg119.java from lesson 80
Copyright 1997, R.G.Baldwin
*/

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

public class SampProg119 {
  public static void main(String[] args){
    //instantiate a Graphical User Interface object
    GUI gui = new GUI();
  }//end main
}//end class SampProg119
//---------------------------------------------------------

//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
//---------------------------------------------------------

class GUI {
  public GUI(){//constructor
    //create a new Frame object
    MyFrame displayWindow = new MyFrame();
    displayWindow.setSize(300,300);
    displayWindow.setTitle("Copyright 1997, R.G.Baldwin");
    displayWindow.setVisible(true);
    
    //Instantiate and register a Listener object that will 
    // terminate the program when the user closes the 
    // window.
    displayWindow.addWindowListener(new WProc1());
    
    //Instantiate and register a Listener object that will 
    // process mouse events to determine and display the 
    // coordinates when the user presses the mouse button.
    displayWindow.addMouseListener(
      new MProc1(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. 
class MProc1 extends MouseAdapter{
  MyFrame refToWin; //save a reference to the window here
  
  MProc1(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 the Frame object.
    refToWin.clickX = e.getX();
    refToWin.clickY = e.getY();
    refToWin.repaint();//display coordinate information
  }//end mousePressed()
}//end class MProc1
//---------------------------------------------------------
class WProc1 implements WindowListener{
  public void windowClosed(WindowEvent e){}
  
  public void windowIconified(WindowEvent e){}
  
  public void windowOpened(WindowEvent e){}

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

  public void windowDeiconified(WindowEvent e){}

  public void windowActivated(WindowEvent e){}

  public void windowDeactivated(WindowEvent e){}
}//end class Wproc1
Q - Modify the program named Event08 to eliminate the requirement to pass a reference to the Frame object to the constructor of the Window listener in order to make the Frame become invisible.

A - See program below.
 
/*File Event08A.java Copyright 1997, R.G.Baldwin
Modify the program named Event08 to eliminate the
requirement to pass a reference to the Frame object to
the constructor of the Window listener in order to make
the Frame become invisible.

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.

Briefly, this application instantiates an object which 
creates a user interface consisting of a simple Frame 
object.  This object is an Event Source which 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 the Adapter classes is to 
implement the basic Listener interfaces and override all of
the methods with empty methods.  Classes which extend the 
Adapter classes can then selectively override only those 
methods of interest.  This Listener object overrides only 
two of the methods.

This application illustrates the requirement to replace the
resize() method from JDK 1.0.2 with the setSize() method 
from JDK 1.1, and to replace the show() method from 
JDK 1.0.2 with the setVisible() method from JDK 1.1.  Note 
that there are many other methods which must be similarly 
replaced when converting JDK 1.0.2 applications to JDK 1.1
applications but these are the only two which occurred in 
this application.

Note that this application does not terminate.  You must 
forcefully terminate it.

When executed, this application places a simple empty Frame
object on the screen.  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 (This dup is not a typo)

Closing the Frame by pressing the X-icon in the upper right
of the Frame produces the following output and causes the
Frame to become invisible.

WProc1 windowClosing test msg
WProc1 windowDeactivated test msg

Note that none of these activities invoked the 
WindowClosed() or WindowOpened() methods.

These results were produced using JDK 1.1.3 running under 
Windows 95.
*/
//=======================================================//

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

public class Event08A {
  public static void main(String[] args){
    //instantiate a Graphical User Interface object
    GUI gui = new GUI();
  }//end main
}//end class Event08A

//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");
    
    displayWindow.setVisible(true);
    
    //Instantiate and register the Listener objects for 
    // notification of Window events. Note that anonymous
    // instantiation of the Listener objects is used and
    // no reference to the Frame object is passed to the
    // constructor for the Listener objects.
    displayWindow.addWindowListener(new WProc1());
    displayWindow.addWindowListener(new WProc2());

  }//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 invoked.
class WProc1 implements WindowListener{
  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");
    //Note the following use of the incoming object to
    // access the Frame object.
    e.getComponent().setVisible(false);    
  }//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 which can be used to avoid the requirement to 
// override all of the methods of the actual Listener class
// named WindowListener.  The Adapter named WindowAdapter 
// implements WindowListener and overrides all of the
// required methods with empty methods which can be 
// selectively overridden.  This class overrides only two of
// the methods declared in the interface.  It displays a 
// message whenever one of the methods is invoked.
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
//=======================================================//
Q - Rewrite the program named Event09 to eliminate the requirement to pass a reference to the MyFrame object to the constructor for the Mouse Listener object.

A - See program below.
 
/*File Event09A.java Copyright 1997, R.G.Baldwin
Rewrite the program named Event09 to eliminate the 
requirement to pass a reference to the MyFrame object to
the constructor for the Mouse Listener object.

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.

These results were produced using JDK 1.1.3, running under 
Windows 95.
*/
//=======================================================//
import java.awt.*;
import java.awt.event.*;

public class Event09A {
  public static void main(String[] args){
    //instantiate a Graphical User Interface object
    GUI gui = new GUI();
  }//end main
}//end class Event09A
//=======================================================//

//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
    MyFrame displayWindow = new MyFrame();
    displayWindow.setSize(300,300);
    displayWindow.setTitle("Copyright 1997, R.G.Baldwin");
    displayWindow.setVisible(true);
    
    //Instantiate and register Listener object which will 
    // terminate the program when the user closes the 
    // Frame.
    WProc1 winProcCmd1 = new WProc1();
    displayWindow.addWindowListener(winProcCmd1);
    
    //Instantiate and register Listener object which will 
    // process mouse events to determine and display the 
    // coordinates when the user presses the mouse button.
    // Note that the Listener object is instantiated
    // anonymously and no reference to the MyFrame object
    // is passed to the constructor for the Listener 
    // object.
    
    displayWindow.addMouseListener(new MouseProc());    
  
  }//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.
class MouseProc extends MouseAdapter{
  //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 the mouse pointer and
    // store in the instance variables of the MyFrame
    // object.  Note the requirement to cast the component
    // to the type of MyFrame in order to access the 
    // instance variables.    
    ((MyFrame)e.getComponent()).clickX = e.getX();
    ((MyFrame)e.getComponent()).clickY = e.getY();
    //display coordinate information    
    e.getComponent().repaint();
    
  }//end mousePressed()
}//end class MouseProc
//=======================================================//

//The following listener is used to terminate the program 
// when the user closes the frame.
class WProc1 extends WindowAdapter{
  public void windowClosing(WindowEvent e){
    System.exit(0);
  }//end windowClosing()
}//end class WProc1
//=======================================================//
Q - Modify the programs named SampProg117, SampProg118, and SampProg119 to eliminate the requirement to pass references to the constructors for the Listener objects when the listener objects are instantiated.

A - See example programs above named Event08A and Event09A for clues as to how to accomplish this requirement.

-end-