#

| Chapter 7 |

# 7. Events

Contents:
The Java 1.0 Event Model
Scribbling in Java 1.0
The Java 1.1 Event Model
Scribbling in Java 1.1
Scribbling with Inner Classes
Inside the Java 1.1 Event Model

The heart of any applet or graphical user interface is the event processing code. Graphical applications are event-driven: they do nothing until the user moves the mouse or clicks a button or types a key. An event-driven program is structured around its event-processing model, so a solid understanding of event handling mechanisms is crucial for good programming.

Unfortunately, the Java event handling model has changed between Java 1.0 and Java 1.1. The Java 1.0 model is a simple one, well suited to writing basic applets. It has a number of shortcomings, however, and does not scale well to complicated interfaces. Although the 1.0 event model is deprecated in Java 1.1, you'll still need to use it for any applets that you want to run on Web browsers based on Java 1.0. The Java 1.1 event model solves many of the shortcomings of the 1.0 model it replaces, but would be quite cumbersome to use if it were not for the new inner class features also introduced in Java 1.1. This chapter covers both event models and provides examples of each.

## 7.1 The Java 1.0 Event Model

In Java 1.0, all events are represented by the `Event` class. This class has a number of instance variables that describe the event. One of these variables, `id`, specifies the type of the event. `Event` defines a number of constants that are the possible values for the `id` field. The `target` field specifies the object (typically a `Component`) that generated the event, or on which the event occurred (i.e., the source of the event). The other fields may or may not be used, depending on the type of the event. For example, the `x` and `y` fields are defined when `id` is `BUTTON_EVENT`, but not when it is `ACTION_EVENT`. The `arg` field can provide additional type-dependent data.

Java 1.0 events are dispatched first to the `handleEvent()` method of the `Component` on which they occurred. The default implementation of this method checks the `id` field of the `Event` object and dispatches the most commonly used types of events to various type-specific methods, listed in Table 7.1.

Table 7.1: Java 1.0 Event Processing Methods of Component
`action()` | `lostFocus()` | `mouseExit()`
`gotFocus()` | `mouseDown()` | `mouseMove()`
`keyDown()` | `mouseDrag()` | `mouseUp()`
`keyUp()` | `mouseEnter()` |

The methods listed in Table 7.1 are defined by the `Component` class. One of the primary characteristics of the Java 1.0 event model is that you must override these methods in order to process events. This means that you must create a subclass to define custom event-handling behavior, which is exactly what we do when we write an applet, for example. Notice, however, that not all of the event types are dispatched by `handleEvent()` to more specific methods. So, if you are interested in `LIST_SELECT` or `WINDOW_ICONIFY` events, for example, you have to override `handleEvent()` itself, rather than one of the more specific methods. If you do this, you should usually invoke `super.handleEvent()` to continue dispatching events of other types in the default way.

The `handleEvent()` method, and all of the type-specific methods, return `boolean` values. If an event-handling method returns `false`, as they all do by default, it means that the event was not handled, so it should be passed to the container of the current component to see if that container is interested in processing it. If a method returns `true`, on the other hand, it is a signal that the event has been handled and no further processing is needed.

The fact that unhandled events are passed up the containment hierarchy is important. It means that we can override the `action()` method (for example) in an applet in order to handle the `ACTION_EVENT` events that are generated by the buttons within the applet. If they were not propagated up as they are, we would have to create a custom subclass of `Button` for every button we wanted to add to an interface!

In programs that use the Java 1.0 event model, it is typical to handle events at the top-level component. In an applet, for example, you override the `handleEvent()` method, or some of the other type-specific methods, of the `Applet` subclass you create. Or, in a stand-alone program that creates its own window, you subclass `Frame` to provide definitions of the event-handling methods. When a program displays a dialog box, it subclasses `Dialog` to define the methods. With complex interfaces, the event-handling methods of the containers at the top of the hierarchy can become long and somewhat convoluted, so you need to be careful when writing them.

### Components and Their Events

In the Java 1.0 model, there is no defacto way to know what types of events are generated by what GUI components. You simply have to look this information up in the documentation. Additionally, different components use different fields of the `Event` object, and pass different values in the `arg` field of that object. Table 7.2 lists each of the AWT components, and for each one, lists the type of events it generates. The first column of the table specifies both the type of the component and the type of the event. The event type is the constant stored in the `id` field of the `Event`.

The second through sixth columns indicate whether the `when` (timestamp), `x` (mouse x coordinate), `y` (mouse y coordinate), `key` (the key that was pressed), and `modifiers` (modifier keys that were down) fields are set for a given event. If a dot appears in this column, the event sets a value for the corresponding field. The seventh column explains what occurred to trigger the event, and what the value of the `arg` field of the `Event` object is.

Events listed for the `Component` component type apply to all `java.awt Component` subclasses. The events listed for the `Window` component type also apply to the `Window` subclasses, `Dialog` and `Frame`.

Table 7.2: AWT Components and the Java 1.0 Events They Generate
Component | when | x | y | key | mods | Event Meaning
--- | --- | --- | --- | --- | --- | ---
Event Type (`id`) | `arg` (Type: value)
`Button` |  |  |  |  |  | User clicked on the button
`ACTION_EVENT` |  |  |  |  |  | `String`: the button label
`Checkbox` |  |  |  |  |  | User clicked on checkbox
`ACTION_EVENT` |  |  |  |  |  | `Boolean`: new checkbox state
`Choice` |  |  |  |  |  | User selected an item
`ACTION_EVENT` |  |  |  |  |  | `String`: label of selected item
`Component` |  |  |  |  |  | Got input focus
`GOT_FOCUS` |  |  |  |  |  | unused
`Component` | * | * | * | * | * | User pressed a function key
`KEY_ACTION` |  |  |  |  |  | unused--`key` contains key
|  |  |  |  |  | constant
`Component` | * | * | * | * | * | User released a function key
`KEY_ACTION_RELEASE` |  |  |  |  |  | unused--`key` contains key
`` |  |  |  |  |  | constant
`Component` | * | * | * | * | * | User pressed a key
`KEY_PRESS` |  |  |  |  |  | unused--`key` contains ASCII
`` |  |  |  |  |  | key value
`Component` | * | * | * | * | * | User released a key
`KEY_RELEASE` |  |  |  |  |  | unused--`key` contains ASCII
`` |  |  |  |  |  | key value
`Component` |  |  |  |  |  | Lost input focus
`LOST_FOCUS` |  |  |  |  |  | unused
`Component` | * | * | * |  |  | Mouse entered the Component
`MOUSE_ENTER` |  |  |  |  |  | unused
`Component` | * | * | * |  |  | Mouse left the Component
`MOUSE_EXIT` |  |  |  |  |  | unused
`Component` | * | * | * |  | * | User pressed mouse button
`MOUSE_DOWN` |  |  |  |  |  | unused
`Component` | * | * | * |  | * | User released mouse button
`MOUSE_UP` |  |  |  |  |  | unused
`Component` | * | * | * |  | * | User moved mouse
`MOUSE_MOVE` |  |  |  |  |  | unused
`Component` | * | * | * |  | * | User dragged mouse
`MOUSE_DRAG` |  |  |  |  |  | unused
`List` |  |  |  |  |  | User double-clicked on an item
`ACTION_EVENT` |  |  |  |  |  | `String`: label of activated item
`List` |  |  |  |  |  | User selected an item
`LIST_SELECT` |  |  |  |  |  | `Integer`: index of selected item
`List` |  |  |  |  |  | User deselected an item
`LIST_DESELECT` |  |  |  |  |  | `Integer`: index of deselected item
`MenuItem` |  |  |  |  |  | User selected an item
`ACTION_EVENT` |  |  |  |  |  | `String`: label of selected item
`Scrollbar` |  |  |  |  |  | User requested scroll
`SCROLL_LINE_UP` |  |  |  |  |  | `Integer`: position to scroll to
`Scrollbar` |  |  |  |  |  | User requested scroll
`SCROLL_LINE_DOWN` |  |  |  |  |  | `Integer`: position to scroll to
`Scrollbar` |  |  |  |  |  | User requested scroll
`SCROLL_PAGE_UP` |  |  |  |  |  | `Integer`: position to scroll to
`Scrollbar` |  |  |  |  |  | User requested scroll
`SCROLL_PAGE_DOWN` |  |  |  |  |  | `Integer`: position to scroll to
`Scrollbar` |  |  |  |  |  | User requested scroll
`SCROLL_ABSOLUTE` |  |  |  |  |  | `Integer`: position to scroll to
`TextField` |  |  |  |  |  | User struck <Return>
`ACTION_EVENT` |  |  |  |  |  | `String`: user's input text
`Window` |  |  |  |  |  | Window was destroyed
`WINDOW_DESTROY` |  |  |  |  |  | unused
`Window` |  |  |  |  |  | Window was iconified
`WINDOW_ICONIFY` |  |  |  |  |  | unused
`Window` |  |  |  |  |  | Window was deiconified
`WINDOW_DEICONIFY` |  |  |  |  |  | unused
`Window` |  | * | * |  |  | Window was moved
`WINDOW_MOVED` |  |  |  |  |  | unused

### Key and Modifier Constants

The `java.awt.Event` class contains the field `key`, which is filled in when a keyboard event has occurred, and the field `modifiers`, which list the keyboard modifier keys currently in effect for key and mouse events.

Four modifier constants are defined by the `java.awt.Event` class; they are listed in Table 7.3. They are mask values that are ORed into the `modifiers` field. You can test for them using AND. You can also check a given event for the first three of the modifiers with the `Event` methods `shiftDown()`, `controlDown()`, and `metaDown()`.

Table 7.3: Java Keyboard Modifiers
Modifier Constant | Meaning
--- | ---
`Event.SHIFT_MASK` | SHIFT key is held down (or CAPS LOCK on)
`Event.CTRL_MASK` | CONTROL key is held down
`Event.META_MASK` | META key is held down
`Event.ALT_MASK` | ALT key is held down

When a `KEY_PRESS` or `KEY_RELEASE` event occurs, it means that the user pressed a key that is a normal printing character, a control character, or a non-printing character with a standard ASCII value--one of RETURN (ASCII 10 or '`\n`'), TAB (ASCII 9 or '`\t`'), ESCAPE (ASCII 27), BACKSPACE (ASCII 8), or DELETE (ASCII 127). In this case, the value of the `key` field in the event is simply the ASCII value of the key that was pressed or released.

When a `KEY_ACTION` or `KEY_ACTION_RELEASE` event occurs, it means that the user pressed some sort of function key, one which does not have an ASCII representation.

`java.awt.Event` defines constants for each of these function keys, which are listed in Table 7.4.

Table 7.4: Java Function Key Constants
Key Constant | Meaning
--- | ---
`Event.HOME` | HOME key
`Event.END` | END key
`Event.PGUP` | PAGE UP key
`Event.PGDN` | PAGE DOWN key
`Event.UP` | UP arrow key
`Event.DOWN` | DOWN arrow key
`Event.LEFT` | LEFT arrow key
`Event.RIGHT` | RIGHT arrow key
`Event.F1 to Event.F12` | Function keys 1 through 12

### Mouse Buttons

In order to maintain platform independence, Java only recognizes a single mouse button--the `Event` class does not have any kind of `mouseButton` field to indicate which button has been pressed on a multi-button mouse.

On platforms that support two- or three-button mouses, the right and center buttons generate mouse down, mouse drag, and mouse up events as if the user were holding down modifier keys, as shown in Table 7.5.

Table 7.5: Mouse Button Modifiers
Mouse Button | Flag Set in Event.modifiers Field
--- | ---
Left button | none
Right button | `Event.META_MASK`
Middle button | `Event.ALT_MASK`

Using keyboard modifiers to indicate the mouse button that has been pressed maintains compatibility with platforms that only have one-button mouses, but still allows programs to use the right and middle buttons on platforms that support them. Suppose, for example, you want to write a program that allows the user to draw lines with the mouse using two different colors. You might draw in the primary color if there are no modifier flags set, and draw in the secondary color when the `META_MASK` modifier is set. In this way, users with a two- or three-button mouse can simply use the left and right mouse buttons to draw in the two colors; and users with a one-button mouse can use the META key, in conjunction with the mouse, to draw in the secondary color.

Signed Applets |  | Scribbling in Java 1.0