Events in JDK 1.0 : Java Glossary

*0-9ABCDEFGHIJKLMNOPQRSTUVWXYZ (all)

Events in JDK 1.0

Introduction

Events are:

Events are now handled in a more efficient way in Java version 1.6 or later. This essay describes the old technique. See my essay on the Java version 1.1 or later event model. I suggest you read some other essays on events such as Richard Baldwin’s instructional essays

The java.awt class lets you write in a platform-independent way to hook into the native GUI API. The native GUI informs your application of various things the user has done by very indirectly generating event objects and passing them as parameters to the postEvent of the affected component which in turn hands it to the handleEvent method. Nothing is more confusing to the new Java programmer than events. They are doubly confusing because they work quite differently than in other windowing systems and because there is almost no documentation on how they work.

An AWT event has a life cycle something like the Pacific salmon. The salmon is born in a stream, migrates to the sea, then, if it isn’t killed in the ocean, returns to the stream where it was born and dies.

The AWT event starts in the native GUI, percolates up through the peer, button, panel, window in the Java application and returns to the peer and back to the native GUI.

The best way to describe this is to hitch a ride on an event and watch how it percolates from birth to death on the event processing assembly line.

Overview

An event is an object passed to a postEvent routine which turn calls a handleEvent routine which in turn calls an action routine such as action, mouseDown. That component may then optionally pass the event back up to its parent for further processing. Event types also include more abstract higher-level events such as WINDOW_DESTROY, SCROLL-PAGE-UP, WINDOW_ICONIFY and LIST_SELECT.

Where is the Event Loop?

People who cut their teeth in the Windows or Mac native low level GUI API are used to writing application-specific code to handle dispatching using an event processing loop. The AWT handles this all automatically and invisibly. It reads the stream of native GUI event messages and translates them, creating Java events, which it puts in the SystemEventQueue. The thread that processes events, when it finishing processing one event, goes and picks up another event off the head of the event queue to dispatch. This is very thread that executes most of your application code.

The loop that processes events does not even start until your main program has returned!! This event loop code is not visible to the application programmer.

How a Button Press Works

For each button on the screen there are three objects:
  1. the application program’s awt.Button object.
  2. AWT’s awt.peer.ButtonPeer object for interfacing to the native GUI. (There may actually be several peer objects, some of them hidden.)
  3. possibly the native GUI’s totally mysterious internal button object.
To kick this all off, the user clicks the mouse on a button.

The native GUI looks in the peers and/or its private tables to narrow down which app and within that which panel and within that which button was pressed and generates a native GUI event which is handed over to the corresponding ButtonPeer object in the AWT (Advanced Windowing Toolkit). Alternatively it may just create a native GUI event message.

The narrowing logic all happens totally behind the AWT’s back. It is the native GUI’s problem to figure out which component in a container was clicked by analysing x-y coordinates and comparing them with bounding rectangles.

The native GUI may change the look of the button at this point, e.g. to make it look pressed. The peer object and native GUI will get a second crack at processing the event later, but it most likely will do all of its processing now.

Sometimes the native GUI handles dispatching — finding the corresponding peer object to give the event to. Sometimes the AWT peer logic has to do it. Application programmers need not concern themselves with either narrowing or dispatching.

From the Java programmer’s point of view an event magically appears at the bottom of the hierarchy directly at the corresponding ButtonPeer object.

The AWT then constructs a Java-style corresponding event object to announce that a button has been clicked.

What Does an Event Look Like?

An event is just an object with instance variables. The event object has 10 public fields. The most important are:
Event.id
ACTION_EVENT, type of event
event.target
reference to the application programmer’s Java-style awt.Button object.
event.arg
string label on the button
event.x
x of mouse. In a component-relative coordinate system i.e. Precisely where inside the button did he click
event.y
y of mouse

What Kinds of Event are there?

Events are classified by the event.id field which can have the following values:
ACTION_EVENT
user clicked a button
KEY_PRESS
user pressed a key, including ASCII control chars such as tab, \b, \r, \n, \u007f=Del
KEY_RELEASE
user let go of a key.
KEY_ACTION
user pressed a function key or control key such as Home or PgUp.
KEY_ACTION_RELEASE
use let go of a function key.
GOT_FOCUS
keystrokes will now be directed here
LOST_FOCUS
keystrokes will be directed elsewhere
MOUSE_ENTER
mouse entered the component
MOUSE_EXIT
mouse left the component
MOUSE_DOWN
user pressed the mouse button
MOUSE_UP
user let go of the mouse button
MOUSE_MOVE
mouse moved
MOUSE_DRAG
user dragged the mouse, (moved with button down)
LIST_SELECT
user clicked on one of the items in a list
LIST_DESELECT
user clicked off one of the items in a list
SCROLL_LINE_UP
user requested a scroll up
SCROLL_LINE_DOWN
user requested a scroll down
SCROLL_PAGE_UP
user requested a scroll up
SCROLL_PAGE_DOWN
user requested a scroll down
SCROLL_ABSOLUTE
user requested scroll to a particular point.
WINDOW_DESTROY
window is being destroyed
WINDOW_ICONIFY
window is being shrunk down to an icon
WINDOW_DEICONIFY
window is being blown back up from an icon
WINDOW_MOVED
window is being moved
Not all these types of event percolate through each component. For most standard components many events never even make it out of the native GUI (Graphic User Interface).

How Events Percolate

The AWT then calls the postEvent method for the awt.Button object, passing the event as a parameter. The default code for event percolation (in the new model) looks like this: As you can see, postament immediately calls handleEvent for the button and waits for the event to percolate all the way up through the event handlers of the parents of this component. postEvent does not put the event in a queue for later handling. All the processing for an event happens in one sweep, before any other event is processed.

handleEvent then classifies the event and hands it off to more specific event handlers like mouseDown and action.

If the button’s handleEvent returns true it means kill the event. Returning true means the event is totally and completely handled and nothing further should be done with it anywhere. If the event handler returns false it means there is still more to be done with this event. The event handler may or may not have modified the event object or done some work behalf of the button-pressing quite independently of whether it returns true or false.

Normally it will return false. If it returns true, the event will never return to the native GUI, which may result in its effect being totally suppressed.

postEvent then looks at the return code from the button’s handleEvent. If it is true, it just returns, effectively killing the event. If the button’s handleEvent returns false, postEvent finds the button’s parent (not its superclass!) i.e. its containing panel. It transforms the x,y in the event object into the coordinate system that the parent panel uses — i.e. where in the entire panel the mouse was clicked. handleEvent then calls postEvent of the button’s parent — i.e. the panel containing the button — handing it the same event object.

The event percolates up the tree, until either somebody handles it and kills it or it bubbles off the top and is handled back to the ButtonPeer object i.e. back to the native GUI. Java In A Nutshell shows code modeled on the old model of event handlers, where typically the default handleEvent for the generic button would do nothing, just return false. The button’s postEvent would then pass the event onto the enclosing panel. The panel’s handleEvent would classify the event and pass it on to the panel’s action. action would typically be an overridden application method that figures out which of the panel’s buttons had been pressed by examining the Event.Target and Event.arg fields (happily examining x,y is usually NOT necessary). action would then finally do something useful — like display a graph — i.e. whatever the user wanted to happen when she clicked the button.

The panel’s handleEvent then would return true to indicate everything that needs to happen as a result of the button being pressed is now complete. This kills the event and stops further percolation.

In the new model, all works the same, except that every event handler returns false so that the event continues to percolate all the way back to the native GUI again.

Some programmers might prefer to write an overriding handleEvent for the individual button that directly called the relevant application code, to create a classes of smart components that could accept callback delegate objects.

How a Keypress Works

Keypress logic is currently buggy in some implementations, notably Windows 95. However, here is how it is supposed to work in the new model. For a keypress to have any effect it MUST make it all the way back to the native GUI. Application code may modify or suppress the keystroke as it percolates. The intent is to allow filtering, censoring, blocking or transformation of the keystroke, e.g. converting it into lower case. On the same percolating pass, application code must also process the keystroke if the native GUI component can’t do it all on its own.

A parent cannot censor what keystrokes its children see. Event percolation works the other way around. The kids alone decide what they want their parents to know.

Let us say that the user hit the Z key while the focus was on a listbox (java.awt.Listawt.List) component. Her intent is to select Zebra from a list of animals presented.

The KEY_PRESS event starts at the bottom at the peer listbox component’s postEvent. The peer hands the event off to the AWT listbox component by calling its postEvent. The event would normally percolate all the way to the top without modification or any other action. The handleEvent for each level would just return false. Event handlers may optionally modify the event.key or the event.modifiers on the way through. If any event handler returns true, that stops dead any further processing of the keystroke. It will be as if the Z key had never been pressed.

If the KEY_PRESS event successfully percolates all the way to the top with no event handler killing it, it eventually reaches the list box peer component again. The peer then hands the (possibly-modified) keystroke back to the native GUI for further processing. Now, when it sees the event for the secord time, the native GUI does the bulk of the keystroke processing work. This contrasts with button processing where the bulk of the native GUI work happens before the event percolates.

What Sorts of Components See What Sorts of Events?

You might wonder if the awt peer or awt list box component sees ACTION events or more primitive MOUSE_DOWN/MOUSE_UP events or both. Surprisingly this is not documented. Exactly what happens depends rather too much on what the native GUI is willing to provide.

How the work is split between the peer and the GUI and the awt component is still in flux.

Writing your own Custom Component

If you wanted to create your own custom component, e.g. a dot that changed colour each time it was pressed, cycling through red, yellow, green, what duties would your code have to perform? What kinds of event would you receive? What sorts of event would you be expected to generate?

Unfortunately the answers to these questions are not yet documented. Your best bet is to just see what sorts of events arrive and code to that, then test your code on other platforms and adjust until it finally works everywhere. Ouch!

The lack of documentation on event processing may be deliberate. I think the idea is your program should not depend on how the AWT works inside. This has deliberately been left undefined. Your code should fly even if there is only a single thread processing all paint requests and events. Some may claim it should also fly even if there are 10,000 threads attempting to process every event fully simultaneously even for the same component. If you need serialization, you should be using synchronised methods.

Repercussions

In practice, an event must be completely handled before another can be processed. Don’t do anything time consuming to process an event or you will stall the processing of all events.

Instead, spin off time-consuming work to be done on a new thread, or enqueue it to be done later by a fixed set of worker threads that process work request packets in the background. Be wary of thread fission.

In some systems, your repaint logic can’t even start until the current event has been completely handled. Doing a Thread.sleep just stalls event processing, making matters even worse. Don’t go to sleep in the middle of processing an event!

You might think the best way to a handle a time-consuming event handling task is to do some of the work then post an event to yourself to tell you where to carry on later, as you might under Windows 3.1. This won’t work. postEvent does not enqueue events. It does not return until the posted event has been totally handled. You could, of course, invent your own queuing mechanism.

Painting

Painting is handled by a totally separate mechanism nothing to do with events. When you invoke repaint, it sends a message to the native GUI suggesting that it would be a good idea if sometime in the distant future when it is convenient and things are slack and when the GUI feels in the mood that the painting work should be done.

The native GUI enqueues this request. As windows occlude each other and reveal each other, the native GUI itself decides that certain components, or parts of components also need to be repainted. The native GUI merges all these requests and removes the duplicates. It may reorder them so that background panels are repainted before the overlaying components.

Eventually the GUI will call the update method for a component to be painted, passing it a graphics object describing the region on the screen to be updated complete with clipping region, since quite likely only part of the component needs to be repainted.

The update and paint routines just paint the entire component. They don’t need to be aware of the clipping.

update then typically erases the region using a fillRect and calls paint. A side effect of this painting will be that some of the subcomponents will be overlaid and will need to be repainted. It is not the concern of update nor paint to arrange for this. The native GUI handles that logic all by itself. No application code need concern itself with the problem.

Don’t dawdle in a paint routine. In pracitice, no other painting can be done until your routine completes. In theory, painting is handled by a separate thread from the event handling and can run in parallel, but it seems in practice any stalling in either paint or event processing sometimes holds everything up.

Philosophy

In my opinion the typical application program has no business dealing with individual events. Only the custom controls should see them. This plumbing should be hidden behind the walls. Techniques of hanging callback code off smart components will make it possible for application programmers to ignore these confusing event critters altogether.

Credits

This article would not have been possible without the patient assistance of Jan Newmarch who researched the material. Jan has a chapter in a SAMS book Tricks of The Java Gurus coming out soon that will go into event loops in much more detail.

This page is posted
on the web at:

http://mindprod.com/jgloss/event10.html

Optional Replicator mirror
of mindprod.com
on local hard disk J:

J:\mindprod\jgloss\event10.html
Canadian Mind Products
Please the feedback from other visitors, or your own feedback about the site.
Contact Roedy. Please feel free to link to this page without explicit permission.

IP:[65.110.21.43]
Your face IP:[18.97.14.81]
You are visitor number