Events                                                                                    P. Komisar
                                                                                                minor revision July 26 / 2001 

delegation  -an implementation mechanism in which an object forwards or
delegates a request to another object. The delegate carries out the request
on behalf of the original object.                     -'Design Patterns'  E. Gamma et al.
 

Today visual interfaces are an intrinsic part of programming. Techniques are required
to convert signals or messages generated by  user-activated, virtual components
(i.e.buttons, scrollbars, textfields etc.) into actions performed in a program. Components
generate events asynchronously and require an event-driven model to process their
activities. Since the introduction of JDK 1.1, Java has used the delegation event
model to handle events.

The standard description of how to use the event model with off-the-shelf, awt & swing
components leaves out details that arise when these components are considered in their
JavaBean's context. When a component is studied as an example of the java bean
architecture, it is shown how a source bean 1) keeps track of it's listeners, 2) issues
events and3) calls action methods These extra details are well hidden in the GUI
design and are not neccessary in learning to use Java's visual components effectively

Threads and Event Handling

Event-handling and painting code executes in the event-dispatching thread. (a.k.a
the GUI or AWT thread). This thread loops repeatedly listening for new events which
it intercepts from the underylying windowing system. Waiting causes the thread to block,
(suspend itself so as not to waste CPU cycles) Using a single thread for event dispatching
ensures each event handler will finish before the next one executes. While one event-
handling method is executing, the program's visual interface is frozen and won't repaint or
respond to other actions such as a mouse click. It is for this reason that it is recommended
that the code run from within an event-handling method should not be too time-consuming.
If need be, a new thread should be spawned to accomplish a time intensive task.

// If your action code is going to create a time-intensive process, spawn a new thread to do it
 

Sources, Event objects & Listeners

When a source component is activated, an event object is created, encapsulating
information which describes the event and where it came from. For example, when
a button is clicked an ActionEvent object is created.

Listener classes listen for events. Classes become listeners by implementing one
or more event listener interfaces. Each listener interface has one or more methods,
for which the programmer provides an implementation which becomes the response(s)
to the event generated by the component. The listener methods take event class
objects as arguments (created when the component is activated). The listener
instance is registered with the source component via a method of the form

SourceComponent source = new SourceComponent( );
source.addEventListener(EventListener)

For example, ActionEvent objects are listened for by classes implementing the
ActionListener interface. The ActionListener interface defines one method that
the implementing class must provide an implementation for, as shown in the
following example.

public class ThisListener extends ActionListener{
  public void actionPerformed(ActionEvent ae) {
        // the response to component activation
  };
}
 
 Under the hood of a JavaBean as an Event Source    //    for reference

 Excerpts from the Magelang Intitute tutorial on JavaBeans available at the Sun Java
 Developers site. It provides a view how the source code is related to the listener class.

The Event Source

  Classes register themselves as interested in the event, and they receive notification when 
  the event happens.  When we use event registration methods we see methods patterned 
  like the following representing the registration process: 

                 public synchronized void addListenerType(ListenerType l);
                 public synchronized void removeListenerType(ListenerType l);

  In the event source where these methods are overridden a Vector is used to keep track of 
  the list of listeners. Inside the event source component there would be some code like: 

                     private Vector hireListeners = new Vector( );
                     public synchronized void addHireListener (HireListener l) {
                       hireListeners.addElement (l );
                     }
                     public synchronized void removeHireListener (HireListener l) {
                       hireListeners.removeElement (l);
                     }

  If you are using AWT components, AWT events already have this behavior. Maintaining
  listeners is only  necessary if you are defining custom event types, or adding listeners where 
  they previously were not supplied , (i.e. ActionEvent within a Canvas). Notice the add and 
  remove methods are synchronized to avoid a race condition. Once the event happens, it is
  necessary for the event source to notify all the listeners. For the hiring example, this would 
  translate into a method like the following: 

                     protected void notifyHired ( ) {
                       Vector l;
                       // create Event object
                       HireEvent h = new HireEvent (this);    //  the event object created
                // Copy listener vector so it won't 
                       // change while firing
                        synchronized (this) {
                         l = (Vector) hireListeners.clone( ); 
                // a snapshot of the vector list is taken via the clone method 
                       }
                       for (int i=0;i<l.size();i++) {
                         HireListener hl = (HireListener)l.elementAt (i); 
                         hl.hired(h); 
                       //  while iterating the vector clone, the event-handling
                       //  method is called on each listener instance
                       } 
                     }
.

Adapters

Listener interfaces containing more than one method have 'convenience', counterpart
classes defined called Adapter classes. Adapter classes have empty or stub definitions
for all the methods in the sibling interface class.Using adapter class' eliminates the need
for providing implementations for methods you are not interested in using.

The form of an abstract vs. an empty or stub method

abstract return_typename(parameter-list);
//  An abstract method ends with a semi-colon and has no

 return_typename( parameter-list){  };
//  body while an empty/stub method has empty curly braces
 

Debugging Adapter Classes

The use of Adapter classes can lead to a difficult debugging problem. You need to
keep in mind that you are overriding a perfectly functional empty method. If you don't
override the given method exactly ( i.e make a spelling mistake), you in effect create
a new method which is overlooked when the action occurs, and the empty method
is invoked instead. The net result is code which compiles and runs but doesn't work
as intended.

Common examples of event dispatching is the creation of an an ActionEvent instance
when a user, clicks a button hits ENTER in a textfield, iii) selects a menu item,
iv) double clicks a list item


Syntax formula

The following naming patterns derive from the nomenclature created for java beans
which awt and swing components are examples of.

The following prefixes describe the classic awt event types.
 
 Action  Adjustment   Container  Component
 Focus  Item   Key  Mouse
 Text  Window  MouseMotion

  1) adding the suffix Listener creates the interface name (ie. ActionListener)
  2) adding the suffix Event yields the action event name ie. (ActionEvent)
 

The java.awt.event Package from the JDK 1.2.2 API documentation
 
 Interfaces   The Listener's Purpose  Event Sources
 ActionListener  receiving action events.  Buttons, menus, text fields
 AdjustmentListener   receiving adjustment events.   Scrolling components like JSlider
 AWTEventListener  receiving notification of events 
 dispatched to instances of Component
 or MenuComponent or their subclasses.
 most apps shouldn't use this
 listener 
 ComponentListener  receiving component events.  modifying a component
 ContainerListener  receiving container events.  adding or removing a 
 component from a container
 FocusListener  receiving keyboard focus 
  events on a component.
 tabbing or requesting focus 
 creates a FocusEvent
 InputMethodListener  receiving input method events.  Input method events contain info 
 about text being composed using an 
 input method. When text changes, 
 the input method sends an event.
 ItemListener  receiving item events.  An item selected from a list or 
 checkbox creates an ItemEvent
 KeyListener  receiving keyboard events   The keyboard creates KeyEvents
 MouseListener  receiving mouse events  (press, 
 release, click, enter, and exit) 
 on a component.
 The mouse creates 
 MouseMotionEvents
 TextListener  receiving text events.  Text Input Controls
 WindowListener  receiving window events.  i.e like closing a window

 

All the event classes in the event package extend the root event class java.util.EventObject.
 
 
Class Summary  // shuffled to seperate the Adapters from the Event classes
 Event Classes
 ActionEvent  A semantic event indicating a component-defined action has occured
 AdjustmentEvent  The adjustment event emitted by adjustable objects.
 ComponentEvent  A low-level event which indicates that a component moved, changed size,
 or changed visibility (the root class for the other component-level events)
 ContainerEvent  A low-level event which indicates that a container's contents changed 
 because a component was added or removed.
 FocusEvent  A low-level event which indicates that a component has gained or 
 lost  the keyboard focus.
 InputEvent  The root event class for all component-level input events.
 InputMethodEvent  Input method events contain information about text that is being 
 composed using an input   method.
 InvocationEvent  An event which executes the run( ) method on a Runnable when 
 dispatched by the AWT event dispatcher thread.
 ItemEvent  A semantic event which indicates that an item was selected or deselected.
 KeyEvent  An event which indicates that a keystroke occurred in a component.
 MouseEvent  An event which indicates that a mouse action occurred in a component.
 PaintEvent  The component-level paint event.
 TextEvent  A semantic event which indicates that an object's text changed.
 WindowEvent  A low-level event which indicates that a window has changed its status.
 Adapter Classes
 ComponentAdapter  An abstract adapter class for receiving component events.
 ContainerAdapter  An abstract adapter class for receiving container events.
 FocusAdapter  An abstract adapter class for receiving keyboard focus events.
  KeyAdapter  An abstract adapter class for receiving keyboard events.
 MouseAdapter  An abstract adapter class for receiving mouse events.
 MouseMotionAdapter  An abstract adapter class for receiving mouse motion events.
 WindowAdapter  An abstract adapter class for receiving window events.

Events are categorized as semantic and low-level. The semantic events are categorized as action, item and
adjustment types.


Summary of AWT Event Relations
 
 Listener Interface  Event Generated   Interface methods  Adapter class
ActionListener ActionEvent actionPerformed
(ActionEvent) 
         ~
AdjustmentListener AdjustmentEvent adjustmentValueChanged
(AdjustmentEvent)
         ~ 
ComponentListener ComponentEvent componentHidden(ComponentEvent)
componentMoved(ComponentEvent)
componentResized(ComponentEvent)
componentShown(ComponentEvent)
ComponentAdapter
ContainerListener ContainerEvent componentAdded(ContainerEvent)
componentRemoved(ContainerEvent)
ContainerAdapter
FocusListener FocusEvent focusGained(FocusEvent)
focusLost(FocusEvent)
FocusAdapter
ItemListener ItemEvent itemStatedChanged(ItemEvent)          ~ 
KeyListener KeyEvent keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
KeyAdapter 
MouseListener  MouseEvent mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
MouseAdapter
MouseMotionLinstener MouseEvent mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
MouseMotionAdapter
TextListener  TextEvent textValueChanged(TextEvent)         ~
WindowListener  WindowEvent windowActivated(WindowEvent)
windowClosed(WindowEvent)
windowClosing(WindowEvent)
windowDeactivated(WindowEvent)
windowDeiconified(WindowEvent)
windowIconified(WindowEvent)
windowOpened(WindowEvent)
WindowAdapter

Table Notes:
1) Note Event classes are provided as arguments to the methods.  i.e. actionPerformed(ActionEvent ae)
2) Adapter classes are provided for any listener interfaces defining more than one method
3) All these event classes and interfaces are made accessible with  import java.awt.event.*;
4) These classic AWT event types are compatible with swing components, which add many new
    event types, i.e. HyperLinkEvent, most which are associated with MVC architecture. To see a list you
    can go to http://developer.java.sun.com/developer/onlineTraining/GUI/Swing2/shortcourse.html

Unlike the AWT event listener classes, there are few adapter classes for the swing event
interfaces at this time. If you have an interest in only one of the event sub-types, you have to
implement all the methods of the interface.



A Look at a few of the Event Classes

The hierarchy of ActionEvent in the diagram below shows ActionEvent derives from
AWTEvent and EventObject. The EventObject class provides the important method
getSource( ) whichreturns the object that originated the event. AWTEvent provides
getID( ) which returns an int value representing the ID of an event. The event's ID
specifies the nature of the event that has occured. For instance a mouse event
contains several (seven) possible actions, a click, a drag etc. A click is represented
by the int stored in, MouseEvent.MOUSE_CLICKED.
 
 

Class ActionEvent         //abreviated from the jdk1.2.2 API


    java.lang.Object 
          |
         +--java.util.EventObject
                |
               +--java.awt.AWTEvent
                      |
                     +--java.awt.event.ActionEvent


public class ActionEvent extends AWTEvent 

  A semantic event which indicates that a component-defined action occured. This high-level 
  event is generated by a component (such as a Button) when the component-specific action 
  occurs (such as being pressed). The event is passed to every every ActionListener object 
  that registered toreceive such events using the component's addActionListener method. 

  The object that implements the ActionListener interface gets this ActionEvent when the 
  event occurs. The listener is therefore spared the details of processing individual mouse 
  movements and mouse clicks, and can instead process a "meaningful" (semantic) event 
  like "button pressed". 

 Field Summary
 

 
 static int ACTION_FIRST  The first # in the range of ids used for action events.
 static int  ACTION_LAST  The last # in the range of ids used for action events.
 static int ACTION_PERFORMED This event id indicates a meaningful action occured.
 static int ALT_MASK   The alt modifier.
 static int CTRL_MASK   The control modifier.
 static int META_MASK   The meta modifier.
 static int  SHIFT_MASK  The shift modifier.

 Constructor Summary
 

 
ActionEvent
(Object source, int id, String command) 
 Constructs an ActionEvent object.
ActionEvent(Object source, int id, 
String command, int modifiers) 
Constructs an ActionEvent object with modifier keys.

Method Summary
 

 
 String  getActionCommand( )  Returns the command string associated with this action.
 int  getModifiers( )   Returns the modifier keys held down during this action event.
 String  paramString( )   Returns a parameter string identifying this action event.
 

Differentiating the event source when the sources use the same listener

In the event that a number of button use the container as the listener via the this keyword,
determining which button was activated can be sorted in a if statement using the method
getSource( ), which returns the reference to the event source. getSource( ) is defined in
java.util.EventObject, the root event class from which the other event classes extend.
You may also use the string associated with a component for identification using the
ActionEvent method, getActionCommand( ). The following two examples show both
methods in action.

Example 1

  public void actionPerformed(ActionEvent ae){
      Object source=ae.getSource( );                         // using getSource() to differentiate source
        if (source.equals(jb1)){
           j1Text.setText("A character");
          }
       else if (source.equals(jb2))
          j2Text.setText("Another character");
    // etc.
    }
}
Example 2

// use String class' trim() method to get rid of leading and trailing spaces

   public void actionPerformed(ActionEvent ae){
       String string = ae.getActionCommand( )
          if ( string.equals( "Name")){
             j1Text.setText( "Your Name");
         else if(e.getActionCommand( ).equals("Address"))
            j2Text.setText("Your Address");
    // etc.
    }
 }


Notice MouseEvent is derived from a hierarchy two generations deeper so inherits more
specialized behaviour than ActionEvent
 
 

  Class MouseEvent     //abreviated from the jdk1.2.2 API


     java.lang.Object
       |
      +--java.util.EventObject
             |
            +--java.awt.AWTEvent
                   |
                  +--java.awt.event.ComponentEvent
                          | 
                         +--java.awt.event.InputEvent
                              |
                             +--java.awt.event.MouseEvent


  public class MouseEvent extends InputEvent 

  An event which indicates that a mouse action occurred in a component. This event is used 
  both for mouse events (click, enter, exit) and mouse motion events (moves & drags). This 
  low-level event is generated by a component object for: 
 

 
 Mouse Events    a mouse button is 1) pressed 2) released 3) clicked 
  (pressed and released) 4) the mouse cursor enters
  a component or 5) exits a component 
 Mouse Motion Events    1) the mouse is moved  2) the mouse is dragged

  A MouseEvent object is passed to every MouseListener or MouseAdapter object which 
  is registered to receive the mouse events via the component's addMouseListener method. 
  (MouseAdapter objects implement the MouseListener interface.) Each such listener object 
  gets a MouseEvent containing the mouse event. 

  A MouseEvent object is also passed to every MouseMotionListener or 
  MouseMotionAdapterobject which is registered to receive mouse motion events using 
  the component's addMouseMotionListener method.  (MouseMotionAdapter objects 
  implement the MouseMotionListener interface.) Each such listener object gets a 
  MouseEvent containing the mouse motion event.
 

 
A Note on processing mice with multi-buttons // just for reference


  When a mouse button is clicked, events are generated and sent to the registered 
  MouseListeners, with the button mask set in the modifier field. For example, if the 
  first mouse button is pressed, events are sent in the following order: 

  MOUSE_PRESSED:  BUTTON1_MASK
  MOUSE_RELEASED: BUTTON1_MASK
  MOUSE_CLICKED:  BUTTON1_MASK

  When multiple mouse buttons are pressed, each press, release, and click results in 
  a separate event. The button mask in the modifier field reflects only the button that 
  changed state, not the current state of all buttons. For example, if the user presses 
  button 1 followed by button 2 and releases them in the same order, the following 
  sequence of events is generated: 

    MOUSE_PRESSED:  BUTTON1_MASK
    MOUSE_PRESSED:  BUTTON2_MASK
    MOUSE_RELEASED: BUTTON1_MASK
    MOUSE_CLICKED:  BUTTON1_MASK
    MOUSE_RELEASED: BUTTON2_MASK
    MOUSE_CLICKED:  BUTTON2_MASK

  If button2 is released first, the MOUSE_RELEASED/MOUSE_CLICKED pair for 
  BUTTON2_MASK arrives first,  followed by the pair for BUTTON1_MASK.

Field Summary
 

 
 static int MOUSE_CLICKED   The "mouse clicked" event
 static int MOUSE_DRAGGED  The "mouse dragged" event.
 static int MOUSE_ENTERED   The "mouse entered" event.
 static int MOUSE_EXITED  The "mouse exited" event.
 static int MOUSE_FIRST   The first number in the range of ids used for mouse events.
 static int MOUSE_LAST   The last number in the range of ids used for mouse events.
 static int  MOUSE_MOVED   The "mouse moved" event.
 static int  MOUSE_PRESSED   The "mouse pressed" event.
static int MOUSE_RELEASED  The "mouse released" event.

Constructor Summary 
 

 
MouseEvent
(Component source, int id, long when, int modifiers, int x, int y, int clickCount, boolean popupTrigger) 
 Constructs a MouseEvent object with the specified source component, type, modifiers, coordinates, and click count.

Method Summary
 

 
 int getClickCount()    Return the # of mouse clicks associated with this event.
 Point getPoint()    Returns x ,y of the event, relative to the source component.
 int getX()    Returns the horizontal x position of the event relative to the 
  source component.
int getY()    Returns the vertical y position of the event relative to the 
  source component.
boolean  isPopupTrigger()    Returns if this mouse event is the popup-menu trigger event 
  for the  platform.
 String paramString()    Returns a parameter string identifying this event.
void  translatePoint(int x, int y)    Translates the event's coordinates to a new position by 
  adding specified offsets.
 


Steps in adding an event listener to a component

1) Create a listener class by implementing a listener interface
2) Create a component which will generate an event
3) Instantiate the listener class  // a new instance
4) call addActionListener( ) on*the component passing in the listener
    class object as the argument.

*Note: 'on' in this context is 'programmer dialect'  meaning 'belonging to' or 'a method of'

Five variations of adding listeners to components


1) An external class listens for a component events

            // inside a class extending JFrame or JApplet

                 JButton b=new JButton("class");
                  ClassicListener c=newClassicListener( ); *
                  b.addActionListener(c);
                 //  . . .

             class ClassicListener implements ActionListener{
                  public void  actionPerformed (ActionEvent ae){
                  System.out.println("classic action invocation");
                  }
              }

This design has some limitation. For instance a listener created outside the constuction
of the GUI won't have references to the components inside the GUI. One way to remove
this limitation is to define the listener with a constructor that takes as arguments the
components you wish to make changes to when actions occur.

    // inside a class extending JFrame or JApplet

Example

// Code showing an externally defined listener defined with a constructor that
// allows GUI components to be passed into it and thereby allowing it to be tied
//  in to the object members defined by the constructor.
 

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

class LisVar extends JFrame{
        LisVar(){
       JButton b=new JButton("class");
       JTextField jt=new JTextField("yes" );
       ClassicListener c=new ClassicListener( jt,"no" );
       b.addActionListener(c);
       getContentPane().add(jt);
       getContentPane().add(b, BorderLayout.NORTH);
       setSize(400,300);
       setVisible(true);
       }
       public static void main(String[]args){
       new LisVar();
       }
    }


2) The containing class instance listens for events

Making the containing class the listener is very popular and common. It has
the advantage of being simple to implement. The disadvantage comes if there
are two many components using this to process their commands. Even still
it is a nice way to handle events and we add a complete example for your
reference.

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
 

class Crate extends JFrame implements ActionListener{
       JButton one,two,three,exit;

        Crate( ){
        getContentPane( ).setLayout(new GridLayout(1,4));
        one= new JButton("One");
        two= new JButton("Two");
        three= new JButton("Three");
        exit= new JButton("Exit");
 

       one.addActionListener(this);
       two.addActionListener(this);
       three.addActionListener(this);
       exit.addActionListener(this);

       getContentPane( ).add(one);
       getContentPane( ).add(two);
       getContentPane( ).add(three);
       getContentPane( ).add(exit);
       }

   public void actionPerformed (ActionEvent ae){
      if (ae.getSource( ).equals(one)){
          System.out.println("It's one");
             }
      if (ae.getSource( ).equals(two)){
            System.out.println("It's two");
            }
      if (ae.getSource( ).equals(three)){
            System.out.println("It's three");
            }
      if (ae.getSource( ).equals(exit)){
            System.out.println("Time to go");
            System.exit(0);
            }
          }
public static void main (String [] args){
  Crate crate=new Crate( );
  crate.setSize(700,100);
  crate.setVisible(true);
  }
}


 
 


3) The component is subclassed to listen to itself

 // again this used in a subclass of the component
 // here, the component is subclassed, the parent constructor is invoked via super from the
 // child constructor, and the component itself is referenced via this

            class SelfAuditButton extends Button implements ActionListener{
              public SelfAuditButton(String label){
                super(label);
                addActionListener(this);
                }
               //next the required, implementation of the interfaces method

            public void actionPerformed(ActionEvent ae){
                System.out.println("action performed by a self listener");
                }
           }


4. An anonymous inner class listens for events

       // This is often seen in Frame and JFrame subclasses to close the window
        // assume frame is a reference to the enclosing frame instantiation

            frame.addWindowListener(new WindowAdapter( ){
                  public void windowClosing(WindowEvent e){
                  System.exit(0);
                  }
              });

Note the characteristic ending   });   which results from having the entire inner class defined as an
argument of the addXXXListener( ) method. Because the inner class is created via the constructor
without being assigned to a named reference it is anonymous. The anonymous inner class a
complicated code structure but it's very popular for taking care of actions which can be described
in a line or two. It tightly binds the action performed with the code which solicits the action.


// Supplemental: our experience showed this worked on AWT components but not swing
 

5. bypass listening and enable the component to process its own events

This is a process called Explicit Event Enabling where a component intercepts it's own
event message and processes them skipping the listening phase altogether. In this technique

1) a component is subclassed
2) this component's method, enableEvents( ) is passed a constant specific to the type of
    event being processed. For action events the constant passed to enableEvents( ) is
    AWTEvent.ACTION_EVENT_MASK. There's one for each type of event.
    This enables the component subclass to process action events.
3) a process method has to be overridden to provide the desired response as well as being
    called in the parent (via super) to obtain the parent class' behaviour. In the case of an
    ActionEvent the method is called proceesActionEvent(ActionEvent ae).

Example class EnabledButton extends Button{
                public EnabledButton(String label){
                super(label);
                enableEvents(AWTEvent.ACTION_EVENT_MASK);
                }
       public void processActionEvent(ActionEvent ae){
                System.out.println("Enabled Button does it's own action");
               super.processActionEvent(ActionEvent ae);   // call to super for button's action listeners
                }
          }