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.
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.
Previous lessons have taught you how to override the handleEvent() method of the Component class and also how to override convenience methods of the Component class in order to respond to events.
In this lesson, we take the subject of event handling one step further by teaching you how to create and distribute Event objects under program control which produce the same response as if the event were caused by an action of the user.
In other words, you can create and distribute Event objects which simulate the behavior of a user.
Recall that you can handle any event by overriding the handleEvent() method.
The handleEvent() method is invoked by the runtime system whenever any event occurs.
(As mentioned in an earlier lesson, the statement above is an oversimplification because there is another method named postEvent() which is also involved in an important way. However, for the purposes of this discussion, we can think in terms of the runtime system communicating directly with the handleEvent() method.)
The fact that you can handle any event by overriding the handleEvent() method continues to be true even if the event is generated by the program as opposed to being generated by a user.
In this lesson, we will not use the convenience methods for handling events. Rather, we will handle all events by overriding the handleEvent() method. I believe that this will provide for consistency and make the material easier to understand.
The constructors for the Event class are shown below (per API Documentation 1.0.2).
public Event(Object target, int id, Object arg); public Event(Object target, long when, int id, int x, int y, int key, int modifiers); public Event(Object target, long when, int id, int x, int y, int key, int modifiers, Object arg);It is not necessary to put valid information in every field in the object. You only need to put information in those fields that will be used by the event handler for the event.
These three overloaded versions of the constructor allow you to put information in selected subsets of fields to support the event handler that will be invoked when the Event object is distributed.
In some cases, you may put "dummy" information in a field if you know that the event handler won't be using information from that field. For example in the sample program later in this lesson, we put a dummy string in the arg field because we know that the event handler won't be using information from that field.
To review the material from an earlier lesson, according to API Documentation 1.0.2, the fields of the object and their purposes are listed below.
The target field is used by the system to determine which component to deliver the Event object to. For example, to simulate a click on a specific Button component, you should create an Event object of the ACTION_EVENT type with the specific Button object specified as the target.
/*File Event03.java Copyright 1997, R.G.Baldwin Primarily designed to illustrates program-generated events. A frame contains a Button and a TextField. When the user clicks the Button, a counter is incremented and displayed in the TextField. If the user clicks in the blank area of the frame, the counter is reset and the coordinates of the mouse pointer are displayed. If the user presses the b or B keys, a KEY_PRESS event is detected, which causes an ACTION_EVENT object to be created and delivered to the Button by using the deliverEvent() method. The result is the same as if the Button had been clicked. This is a program-generated event. Closing the frame terminates the program. Note that there are some focus issues that are not handled in an ideal manner in order to preserve simplicity. In particular, if the first thing that you do is to press the b or B key, nothing happens. */ import java.awt.*; //Make the controlling class extend the Frame class // to produce a graphic window that can accept events. public class Event03 extends Frame{ String msg = ""; //save message for display here int clickX = 0, clickY = 0;//save coordinates for display here Button myButton; //used to instantiate a button object TextField myTextField; //used to instantiate a TextField object int counter = 0; //Because this display is a little more complicated than before // we will to use a constructor to build it. public Event03(){//constructor //put a button at the top of the frame myButton = new Button("Click Here to Increment Counter"); add("North", myButton);//add it to the top of the frame //put a non-editable TextField at the bottom of the frame myTextField = new TextField( "counter = " + counter + " This textField is not editable."); add ("South",myTextField);//add it to the bottom of 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 display the frame public static void main(String[] args){ Event03 displayWindow = new Event03(); //instantiate obj of this type displayWindow.show();//display the frame }//end main //Override handleEvent() method in Component class // to process all events. public boolean handleEvent(Event evObj){ //Terminate program if user closes the window if(evObj.id == Event.WINDOW_DESTROY) System.exit(0); //Display the coordinates and clear the counter when user clicks // in blank portion of the frame. if( (evObj.id == Event.MOUSE_DOWN) && (evObj.target == this)){ clickX = evObj.x; //save mouse coordinates clickY = evObj.y; //construct message for display msg = "" + clickX + ", " + clickY + ", Clear counter"; counter = -1;//clear the counter and modify text in the TextField myTextField.setText( "counter = " + ++counter + " This textField is not editable."); repaint(); //force a repaint of the window }//end if on MOUSE_DOWN in blank portion of frame //Create an action event object and deliver it to the button if the // user presses b or B. if( (evObj.id == Event.KEY_PRESS) && ((evObj.key == 'b') || (evObj.key == 'B')) ){ Event event = new Event(myButton,Event.ACTION_EVENT,"Dummy string"); deliverEvent(event); //postEvent(event); could use postEvent() instead of deliverEvent() }//end if on KEY_PRESS //When the user clicks the button, (or a program-generated action event // is delivered to the button) increment the counter which // uses the textField as a display device. if( (evObj.id == Event.ACTION_EVENT) && (evObj.target == myButton)){ myTextField.setText( "counter = " + ++counter + " This textField is not editable."); }//end if on ACTION_EVENT //Always finish by invoking the handleEvent method in the superclass // to handle any events not handled above. return super.handleEvent(evObj); }//end handleEvent() //Override paint method to repaint the window. This displays // graphic coordinate information in the blank area of the frame. public void paint(Graphics g){ g.drawString(msg, clickX, clickY); }//end paint() }//end class Event03To begin with, we needed a little more GUI in this program than in previous programs in order to have enough tools available to illustrate the concept of program-generated events.
In addition to the Frame object that we have been using in previous programs, we also needed a Button component and a TextField component.
The Button is used to increment a counter whenever it is clicked.
The TextField is used to display the value of the counter.
For the time being, please just accept the fact that the code in the constructor will produce the desired user interface.
We will discuss the issues surrounding the creation of user interfaces using components in detail in several subsequent lessons.
The code that is really of interest here is
We will skip over the section that responds to the WINDOW_DESTROY event to terminate the program. You have seen that before and we didn't make any significant changes in that area.
This code starts out by cracking open the Event object and confirming the occurrence of a MOUSE_DOWN event on the Frame object (represented by this).
if( (evObj.id == Event.MOUSE_DOWN) && (evObj.target == this)){ clickX = evObj.x; //save mouse coordinates clickY = evObj.y; //construct message for display msg = "" + clickX + ", " + clickY + ", Clear counter"; counter = -1;//clear the counter and modify text in the TextField myTextField.setText( "counter = " + ++counter + " This textField is not editable."); repaint(); //force a repaint of the window }//end if on MOUSE_DOWN in blank portion of frame
Then, as in earlier sample programs, the code sets up some information to be displayed by the paint() method when it is invoked, either by calling repaint() or because of some system activity such as restoring the display when things are moved about by the user. You have seen this before.
After that, the code executes some fairly straightforward statements to reset the counter variable to zero and display its value. Then it calls repaint() to force the graphics portion of the display to be repainted.
Except for the fact that this was all included inside the overridden handleEvent() method instead of using a convenience method, there's not much that is too difficult here.
The following code will create an Event object of type ACTION_EVENT and deliver it to the Button object for processing.
The event is created and delivered whenever the user presses the "b" key or the "B" key on the keyboard. The end result of pressing either of these keys is the same as clicking the button with the mouse.
As you can see, the code required to create and distribute a program-generated event is amazingly simple.
if( (evObj.id == Event.KEY_PRESS) && ((evObj.key == 'b') || (evObj.key == 'B')) ){ Event event = new Event(myButton,Event.ACTION_EVENT,"Dummy string"); deliverEvent(event); //postEvent(event); could use postEvent() instead of deliverEvent() }//end if on KEY_PRESS
This code fragment starts out by responding to an event of type KEY_PRESS and confirming that it was the result of pressing either the lower-case or upper-case "B" key. Unless both conditions are satisfied, the code fragment ignores the event leaving it up to handleEvent() to deal with later.
If both conditions are satisfied, the code fragment instantiates a new object of type Event with
The the code fragment invokes the deliverEvent() method to cause the the system to deliver the new Event object to the Button object. This causes the program to behave as though the Button object had received an ACTION_EVENT directly (such as being clicked by the user).
As mentioned earlier, the postEvent() method could also have been used for this purpose, but I am leaving it as an exercise for the student to ferret out the differences, similarities, and relationship between these two methods.
if( (evObj.id == Event.ACTION_EVENT) && (evObj.target == myButton)){ myTextField.setText( "counter = " + ++counter + " This textField is not editable."); }//end if on ACTION_EVENTThere isn't a lot to be said about this code. It simply verifies that the event is an ACTION_EVENT and that the specific Button object is the target, and then increments and displays the counter variable.
//Always finish by invoking the handleEvent method in the superclass // to handle any events not handled above. return super.handleEvent(evObj); }//end handleEvent()-end-