Java and event handling

How events are passed to user interface components, how to create event handlers, and more

Most programs, to be useful, must respond to commands from the user. To do so, Java programs rely on events that describe user actions.

Last month I demonstrated how to assemble a graphical user interface from components provided by the Java class library's abstract windowing toolkit. After assembling a few such interfaces, I spoke briefly about the topic of event handling, but I stopped short of a full description of event handling as implemented by the AWT. This month, we pick up where we left off.

To be event driven

In the distant past, a program that wanted to know what the user was doing had to actively collect such information itself. In practice this meant that after a program initialized itself, it entered a big loop in which it repeatedly looked to see if the user was doing anything interesting (for example, pressing a button, touching a key, moving a slider, moving the mouse) and then took the appropriate action. This technique is known as polling.

Polling gets the job done but tends to be unwieldy when used in modern-day applications for two related reasons: First, the use of polling tends to push all event-handling code into one location (inside the big loop); second, the resulting interactions within the big loop tend to be complex. In addition, polling requires a program to sit in a loop, consuming CPU cycles, while waiting for the user to do something -- a serious waste of a valuable resource.

The AWT solved these problems by embracing a different paradigm, one that underlies all modern window systems: event-driven programming. Within the AWT, all user actions belong to an abstract set of things called events. An event describes, in sufficient detail, a particular user action. Rather than the program actively collecting user-generated events, the Java run time notifies the program when an interesting event occurs. Programs that handle user interaction in this fashion are said to be event driven.

The Event class

The Event class is the primary player in the event game. It attempts to capture the fundamental characteristics of all user-generated events. Table 1 lists the public data members provided by class Event.

ObjecttargetA reference to the component that initially received the event.
longwhenThe point in time at which the event occurred.
intidThe event type (see section Event Types for more information).
intxThe x coordinate at which the action occurred relative to the component that is currently processing the event. For a given event, the x coordinate will change in value as the event moves up the component hierarchy. The origin of the coordinate plane is in the component's upper-left-hand corner.
intyThe y coordinate at which the action occurred relative to the component that is currently processing the event. For a given event, the y coordinate will change in value as the event moves up the component hierarchy. The origin of the coordinate plane is in the component's upper-left-hand corner.
intkeyFor keyboard events, the keycode of the key just pressed. Its value will typically be the Unicode value of the character the key represents. Other possibilities include values for the special keys HOME, END, F1, F2, and so on.
intmodifiersAn arithmetically or'd combination of the values SHIFT_MASK, CTRL_MASK, META_MASK, and ALT_MASK. Its value represents the state of the shift, control, meta, and alt keys, respectively.
intclickCountThe number of consecutive mouse clicks. This data member is only significant in MOUSE_DOWN events.
ObjectargAn event-dependent argument. For Button objects, this object is a String object that contains the textural label of the button.
Table 1: Public data members provided by class Event

As I will explain in the section titled Event dispatch and propagation, an instance of class Event is typically created by the Java run-time system. It is possible, however, for a program to create and send events to components via their postEvent() method.

Event types

As mentioned above, the Event class is a model of a user interface event. Events naturally fall into categories based on the type of the event (the event type is indicated by the id data member). Table 2 lists all of the events defined by the AWT, sorted by category.

Table 2: Events defined by the AWT, sorted by category

It can be instructive to see event generation in action. The button in Figure 1, when pressed, creates an event browser that displays event information about the events the browser receives. The source code for the event browser is available here.

You need a Java-enabled browser to view this applet

Figure 1: Event generation in action

Event dispatch and propagation

Consider the applet in Figure 2. It consists of two instances of the Button class, embedded within an instance of the Panel class. This instance of the Panel class is itself embedded within another instance of the Panel class. The latter instance of the Panel class sits below an instance of class TextArea, and both instances are embedded within an instance of the Applet class. Figure 3 presents the elements that make up this applet laid out as a tree, with the TextArea and Button instances as the leaves, and an Applet instance as the root. (For more information about the hierarchical layout of components in a user interface, read last month's introduction to the AWT.)

You need a Java-enabled browser to view this applet

Figure 2: Classes embedded within classes


Figure 3: Applet elements tree (hierarchy)

When a user interacts with the applet in Figure 2, the Java run-time system creates an instance of class Event and fills its data members with information describing the action. The Java run-time system then allows the applet to handle the event. It begins with the component that initially received the event (for instance, the button that was clicked) and moves up the component tree, component by component, until it reaches the container at the top of the tree. Along the way, each component has the opportunity to ignore the event or to react to it in one (or more) of the following ways:

  • Modify the data members of the Event instance
  • Take action and perform some computation based on the information contained in the event
  • Indicate to the Java run-time system that the event should propagate no further up the tree

The Java run-time system passes event information to a component via the component's handleEvent() method. All valid handleEvent() methods must be of the form

public boolean handleEvent(Event e)

An event handler requires a single piece of information: a reference to the instance of the Event class containing information about the event that just occurred.

The value returned from the handleEvent() method is important. It indicates to the Java run-time system whether or not the event has been completely handled within the event handler. A true value indicates that the event has been handled and propagation should stop. A false value indicates that the event has been ignored, could not be handled, or has been handled incompletely and should continue up the tree.

Consider the following description of an imaginary user's interaction with the applet in Figure 2. The user clicks on the button labeled "One." The Java language run-time system gathers information about the event (the number of clicks, the location of the click, the time the click occurred, and the component that received the click) and packages that information in an instance of the Event class. The Java run-time system then begins at the component that was clicked (in this case, the Button labeled "One") and, via a call to the component's handleEvent() method, offers the component a chance to react to the event. If the component does not handle the event or handles the event incompletely (indicated by a return value of false), the Java run-time system offers the Event instance to the next higher component in the tree -- in this case an instance of the Panel class. The Java run-time system continues in this manner until the event is handled or the run-time system runs out of components to try. Figure 4 illustrates the path of this event as the applet attempts to handle it.


Figure 4: The path of an event

Each component making up the applet in Figure 2 adds a line to the TextArea object that indicates it received an event. It then allows the event to propagate to the next component in the tree. Listing 1 contains the code for a typical handleEvent() method. The complete source code for this applet is available here.

public boolean handleEvent(Event evt) { if ( == Event.ACTION_EVENT) { ta.appendText("Panel " + str + " saw action...\n"); } else if ( == Event.MOUSE_DOWN) { ta.appendText("Panel " + str + " saw mouse down...\n"); }

return super.handleEvent(evt); }

Listing 1: A typical handleEvent() method

Event helper methods

The handleEvent() method is one place a programmer can put application code for handling events. Occasionally, however, a component will only be interested in events of a certain type (for example, mouse events). In these cases, the programmer can place the code in a helper method, rather than placing it in the handleEvent() method.

Here is a list of the helper methods available to programmers. There are no helper methods for certain types of events.

action(Event evt, Object what)

gotFocus(Event evt, Object what)

lostFocus(Event evt, Object what)

mouseEnter(Event evt, int x, int y)

mouseExit(Event evt, int x, int y)

mouseMove(Event evt, int x, int y)

mouseUp(Event evt, int x, int y)

mouseDown(Event evt, int x, int y)

mouseDrag(Event evt, int x, int y)

keyDown(Event evt, int key)

keyUp(Event evt, int key)

false to indicate that the helper method did not handle the event.

The implementation of the handleEvent() method provided by class Component invokes each helper method. For this reason, it is important that the redefined implementations of the handleEvent() method in derived classes always end with the statement

return super.handleEvent(e);

The code in Listing 2 illustrates this rule.

public boolean handleEvent(Event e) { if ( instanceof MyButton) { // do something... return true; }

return super.handleEvent(e); }

Listing 2: Rule for ending statement in handleEvent() method

Failure to follow this simple rule will prevent the proper invocation of helper methods.

Figure 5 contains an applet that handles mouse events solely through code placed in helper methods. The source code is available here.

EventevtThe next event in a linked list of events.
Window events
Window events are generated in response to changes in the state of a window, frame, or dialog.
Keyboard events
Keyboard events are generated in response to keys pressed and released while a component has input focus.
Mouse events
Mouse events are generated in response to mouse actions occurring within the boundary of a component.
Scroll events
Scroll events are generated in response to manipulation of scrollbars.
List events
List events are generated in response to selections made to a list.
Miscellaneous events
Miscellaneous events are generated in response to a variety of actions.
Todd Sundsted has been programming since computers became available in desktop models. Though originally interested in building distributed object applications in C++, Todd moved to the Java programming language when Java became an obvious choice for that sort of thing. In addition to writing, Todd provides Internet and Web application consulting services to companies in the southeastern United States.

Learn more about this topic