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

Event Handling in JDK 1.0.2, Smart Components

Java Programming, Lecture Notes # 72, Revised 8/3/97.

Note: Because the event model for JDK 1.0 is rapidly becoming obsolete, material on the JDK 1.0 event model will not be covered in classroom lectures or examinations in Professor Baldwin's CIS 2103K (Intermediate Java Programming) classes at Austin Community College.


Introduction

The beta version of JDK 1.1 is available for testing at this time, and Sun has announced that it will contain important changes to the Abstract Windows Toolkit, including changes to the implementation of events and event handling.

When JDK 1.1 is released and hard information regarding those changes becomes available, this lesson will be supplemented with a new lesson describing events and event handling under JDK 1.1.

Most user actions associated with a GUI component are probably handled by the container of the component.

Among other reasons, that is the place where it is possible to override the event-handling methods of the Component class in order to provide the desired functionality.

If we want a component to be able to handle its own events, (as opposed to having its events handled by its container) we can extend the class for that component, thereby creating a class for a custom component having all the attributes of the original component.

Then, instead of adding an object of the original component type to our container, we instantiate and add an object of the new custom type.

Having done that, we can write event handlers for the custom component class to handle events at the component level rather than at the container level.

Event Objects come from the Runtime System

The following is my general understanding of how it all fits together in JDK 1.0.2 as of February, 1997. This understanding is based on reading between the lines of a large number of books, specifications, and articles.

As you may recall, a user action involving a GUI component causes the operating system to send a message to the Java runtime system.

The runtime system

In addition to its other duties, the postEvent() method invokes the handleEvent() method for that component, passing the object as a parameter.

One of the duties of the postEvent() method is to handle the task of passing the Event object up the component hierarchy until the handleEvent() method at some level returns true indicating that the event has been handled.

The default handleEvent() method for the component probably returns false, signaling the postEvent() method to invoke the handleEvent() method for the container of the component.

It is at the container level, rather than the component level, where the event normally gets handled, if it gets handled at all. (Many random events never get handled, but simply propagate upward until they are discarded.)

More than likely, you will design the class for the container. In so doing, you can override the handleEvent() method to

There are also a number of convenience event-handler methods that you can override and use as an alternative to the handleEvent() method if you prefer.

You will probably handle those events in which you are interested, and return false for those events that don't interest you, again signaling the postEvent() method to pass the event up to the next higher level container in the hierarchy.

Creating Smart Components

If we we can override the handleEvent() method (and if need be, the postEvent() method) for that class which gives us the ability to handle events at the component (or custom component) level.

One difficulty in doing this is determining in advance whether or not the runtime system will create an Event object and invoke the postEvent() method on the custom component for a specific user action.

The documentation is sketchy at best, and most of the currently published books gloss over the subject.

To give us a concrete example to work with, let's consider the following question:

That is not a particularly easy question to answer. Most of the existing books simply ignore technical issues at this level.

As of February 1997, I am of the opinion that Java in a Nutshell by David Flanagan is one of the best and most informative Java books available.

On page 183, while discussing a chart that follows in his text, Flanagan states:

I believe he is saying that any component that inherits from the Component class, either directly or indirectly, will receive all the event types that he lists under Component.

The chart lists

under Component (plus a number of other event types as well, including GOT_FOCUS).

Since the TextField class extends the TextComponent class which extends the Component class, one would be led to believe that a TextField object should receive all of the mouse events listed above as well as the GOT_FOCUS event.

Alas, such does not seem to be the case as we will see later in our sample program.

When you click the mouse in a TextField object (which involves all of the mouse events listed above except MOUSE_DRAG) the TextField object receives the focus, as evidenced by the blinking I-beam cursor. As a result, one might expect that the object would receive a host of mouse events plus a GOT_FOCUS event.

The sample program for this lesson accomplishes two purposes.

First, it teaches you how to create smart components which can respond to events posted by the runtime system for those components.

Second, it teaches you how to write a simple program by which you can experimentally determine whether or not the runtime system posts an Event object for a specific user action with respect to a specific GUI object of interest.

We will use the sample program in an attempt to answer the question posed above. We will learn some other interesting things in the process as well.

Sample Program

The sample program for this lesson is shown below. A detailed discussion follows the program listing. This discussion includes experimental results obtained for several specific user actions involving a custom TextField object created and used within the program.


/*File Event05.java Copyright 1997, R.G.Baldwin
Primarily designed to illustrate smart components, and a method for
determining the events received by a component.

Closing the frame terminates the program.
*/

import java.awt.*;

//Define a custom TextField class that can respond to events.
//  Note that this class extends TextField.
class TF extends TextField{
  TF(String inString){setText(inString);}//end constructor

  //The following event handler method handles events at the
  // component level as opposed to the container level.
  public boolean handleEvent(Event evObj){
    System.out.println(evObj.toString());//display the Event object
    
    switch(evObj.id){//display type of event
      case Event.KEY_PRESS : 
          setText(getText() + "," + "KEY_PRESS");break;
      case Event.KEY_RELEASE : 
          setText(getText() + "," + "KEY_RELEASE");break;
      case Event.ACTION_EVENT : 
          setText(getText() + "," + "ACTION_EVENT");break;
      default : //catch and display all other event types here
          setText(getText() + "," + evObj.id);
    }//end switch
    return super.handleEvent(evObj);
  }//end handleEvent() in class TF
  
}//end class TF
//===================================================================

//Make the controlling class extend the Frame class to provide
// a container for the custom TextField component
public class Event05 extends Frame{

  public Event05(){//constructor
    TF myTextField = new TF("TF");//instantiate custom TextField object
    add ("Center",myTextField);//add it to the frame
    myTextField.setEditable(false);//make it non-editable

    //Dress the frame up a little    
    setTitle("Copyright 1997, R.G.Baldwin");
    resize(300,200);//set frame size    
   }//end constructor

  //Create and show the frame object
  public static void main(String[] args){
    Event05 displayWindow = new Event05(); //instantiate obj of this type
    displayWindow.show();//display the frame
  }//end main
  
  //Override handleEvent() method relative to the frame for program termination
  public boolean handleEvent(Event evObj){
    //Terminate program if user closes the window
    if(evObj.id == Event.WINDOW_DESTROY) System.exit(0);
    //Always finish by invoking the handleEvent method in the superclass
    return super.handleEvent(evObj);                      
  }//end handleEvent()
  
}//end class Event05
In this program, a smart component in the form of a custom TextField is defined by extending the TextField class. An object of this type is instantiated and placed in a frame which becomes the container for the component.

Because the class definition for the custom component includes an overridden version of handleEvent(), this custom component has the ability to handle its own events rather than simply passing them up to the Frame container for processing.

Due to the design of the overridden handleEvent() method, clicking the custom TextField object to give it the focus at runtime and then pressing a key displays information in the TextField and also displays information on the console screen.

The overridden handleEvent() method is repeated below for convenient viewing.


  public boolean handleEvent(Event evObj){
    System.out.println(evObj.toString());//display the Event object
 
    switch(evObj.id){//display type of event
      case Event.KEY_PRESS : 
          setText(getText() + "," + "KEY_PRESS");break;
      case Event.KEY_RELEASE : 
          setText(getText() + "," + "KEY_RELEASE");break;
      case Event.ACTION_EVENT : 
          setText(getText() + "," + "ACTION_EVENT");break;
      default : //catch and display all other event types here
          setText(getText() + "," + evObj.id);
    }//end switch
    return super.handleEvent(evObj);
  }//end handleEvent() in class TF
As you can see, the information displayed on the console screen is the toString() conversion of the Event object delivered by the runtime system to the postEvent() method and ultimately to the handleEvent() method.

For example, pressing the return key when the TextField object has the focus causes the following information to be displayed on the console (only the beginning portion of each line is shown):

java.awt.Event[id=401,x=0,y=0,key=10,target=TF[4,175,292x21,text=TF,... java.awt.Event[id=1001,x=0,y=0,target=TF[4,175,292x21,text=TF,... java.awt.Event[id=402,x=0,y=0,key=10,target=TF[4,175,292x21,text=TF,...

The integer values

id = 401, 1001, and 402

in the above output are respectively the id-field values for

Pressing the return key when the TextField object has the focus also causes the id field in the Event object to be interpreted by the handleEvent() method and displayed in the TextField.

The following information is displayed in the TextField when the return key is pressed.

Note that the "TF" is placed at the beginning when the custom TextField object is instantiated. The additional text is placed there by code in the handleEvent() method with each new event simply adding more text onto the end of the existing text string.

TF,KEY_PRESS,ACTION_EVENT,KEY_RELEASE

In other words, pressing the return key once causes three separate Event objects to be delivered to the handleEvent() method for the custom TextField object:

As another example, pressing the key for the letter "A" displays the following on the console:

java.awt.Event[id=401,x=0,y=0,key=97,target=TF[4,23,292x173,text=TF,... java.awt.Event[id=402,x=0,y=0,key=97,target=TF[4,23,292x173,text=TF,...

and causes the following to be displayed in the custom TextField.

TF,KEY_PRESS,KEY_RELEASE

In this case, only two events are delivered to the handleEvent() method:

As a final example, pressing the F1 key produces the following on the console:

java.awt.Event[id=403,x=0,y=0,key=1008,target=TF[4,23,292x173,text=TF,... java.awt.Event[id=404,x=0,y=0,key=1008,target=TF[4,23,292x173,text=TF,...

and produces the following in the custom TextField:

TF,403,404

In this case, 403 and 404 are the respective event values of the id field in the Event object for

The switch statement in the handleEvent() method allowed these values to fall into the default clause where the numeric value of the id field rather than a symbolic representation of the event was displayed.

The Answer to the Original Question

The original question was: In no case were any Event objects delivered to either postEvent() or handleEvent() as a result of mouse actions in the vicinity of the custom TextField object.

So the answer to the first part of the question is that apparently the runtime system does not create and pass Event objects when the mouse enters a TextField or clicks in a TextField. A TextField object appears to be immune to mouse events.

Clicking the mouse on the custom TextField object gave it the focus but did not cause an event with an id field containing GOT_FOCUS to be delivered to the postEvent() and handleEvent() methods.

Therefore, the answer to the second part of the question appears to be that the runtime system does not create and pass an Event object whenever a TextField gains the focus.

So, we have used our sample program to experimentally determine the answer to the original question.

Not related to the question, but also interesting was the fact that some keys such as CapsLock, Shift, and Ctrl did not produce a KEY_PRESS event on the downstroke, but did produce a KEY_RELEASE event on the upstroke.

The Alt key did not produce any event unless another key was pressed while the Alt key was being held down, in which case it only produced a KEY_RELEASE event on the upstroke of the Alt key. In this case, pressing and releasing the other key while holding the Alt key down did not produce an event independent of the event produced by releasing the Alt key.

These results were produced using Java JDK 1.0.2 running under Windows 95.

-end-