| Home > Core Java FAQ
> Event Handling FAQ |
| Event
Handling |
| Events
in 1.0 (11) * Event Classes,
Listeners, and Methods (08) * Semantic
Events (04) * Low-Level Events (04) |
| |
|
Q . What information do specific event types in the JDK 1.1 carry?
|
Ans :
JDK 1.1
event objects carry only the information relevant to their
specific event class; you can tell what information is in an event
object by the accessor methods of the event object's class.
Starting
in the JDK 1.1, events in Java are organized by a class hierarchy
rooted at EventObject, in package java.util.
AWTEvent, an immediate subclass of EventObject,
is the base class for all AWT-specific events. Table 7.1 shows the
complete inheritance hierarchy of the 1.1 AWT event classes (all
except AWTEvent are in the java.awt.event
package).
The fields and methods of an event
class are combined from the class itself and all the classes it
inherits from. WindowEvent, for example, inherits
from ComponentEvent, which inherits from AWTEvent,
which inherits from EventObject. Table
shows the public methods supported by each of the event
classes together with the information they yield.
Table
: JDK 1.1 AWT Event Class Hierarchy
AWTEvent
(in java.util) |
ActionEvent |
AdjustmentEvent |
ItemEvent |
TextEvent |
ComponentEvent |
ContainerEvent |
FocusEvent |
WindowEvent |
PaintEvent |
InputEvent |
KeyEvent |
MouseEvent |
Note regarding All
subclasses of EventObject inherit the getSource
method, which returns the object that emitted the event. Several
of the AWT event classes, though, provide their own convenience
accessor method, such as getContainer in class ContainerEvent
and getWindow in class WindowEvent.
These methods return a reference to the same object as getSource
does, but in a class more specific to the event type.
|
|
Q . How do I catch events in the JDK 1.1 event model?
|
Ans :
Determine
which events you want to receive from a given component, provide one
or more objects that implement the corresponding listener
interfaces, and invoke the appropriate add...Listener
method to register your objects with the component.
The
JDK 1.1 event model for the AWT centers around event
listeners—objects whose interface (or interfaces) allows them to
be notified when specific event types occur. The AWT defines a set
of eleven listener interfaces that enable objects to catch specific
event types. The MouseMotionListener interface, for
example, contains two methods, mouseMoved and mouseDragged,
that can notify your program of mouse-move and mouse-drag events.
There are two main parts to working
with event listeners. First, you define a class that implements the
interface. In the case of MouseMotionListener, for
example, you could define the following class:
/* using JDK 1.1: */
class MouseTracker implements MouseMotionListener {
// ...
public void mouseDragged(MouseEvent e) {
// ... handle mouse-drag event
}
public void mouseMoved(MouseEvent e) {
// ... handle mouse-move event
}
}
Second, you register
an instance of the class with a component using the appropriate add...Listener
method; for example:
Canvas aCanvas = ...
aCanvas.addMouseMotionListener(new MouseTracker());
From this point on, any
mouse motion or mouse drag event generated over the aCanvas
instance will trigger invocations of the mouseMoved and
mouseDragged methods in your MouseTracker
class.
Another new feature in the JDK 1.1,
inner classes, makes it significantly easier to define small classes
for local use. An inner class is defined inside another class, which
has two primary benefits: proximity and access. You can define your
inner class right beside the code that uses the class, and your
inner class has direct access to methods, fields, and variables of
the class and/or method within which it is defined. The following
example shows MouseTracker from above rewritten as an
inner class:
class Example {
/** An inner class for tracking mouse motion. */
class MouseTracker implements MouseMotionListener {
public void mouseDragged(MouseEvent e) { /* ... */ }
public void mouseMoved(MouseEvent e) { /* ... */ }
}
public void init() {
// ...
aCanvas.addMouseMotionListener(new MouseTracker());
}
// ...
}
The sample code in this
chapter contains further examples of inner classes.
Table:
Public Methods in each Event Class
| Class |
Method |
Returns |
EventObject |
getSource |
Object:object
that emitted the event |
toString |
String:
string representing the event |
AWTEvent |
2
methods inherited from EventObject |
getID |
int:
identification key for event type |
paramString |
String:
string representing event parameters |
ActionEvent |
4
methods inherited viaAWTEvent |
getModifiers |
int: state
of all modifier keys during action |
getActionCommand |
String:
command name for action |
AdjustmentEvent |
4
methods inherited viaAWTEvent |
getValue |
int:
current value resulting from the event |
getAdjustmentType |
int:
type of adjustment that changed the value |
getAdjustable |
Adjustable:
object that emitted the event |
ItemEvent |
4
methods inherited viaAWTEvent |
getItem |
Object:
item changed by the event |
getStateChange |
int:
type of change-select or deselect |
getItemSelectable |
ItemSelectable:
object that emitted the event |
TextEvent |
4
methods inherited viaAWTEvent |
ComponentEvent |
4
methods inherited viaAWTEvent |
ContainerEvent |
4
methods inherited viaComponentEvent |
getChild |
Component:
child that was added or removed |
getContainer |
Container:
object that emitted the event |
FocusEvent |
4
methods inherited viaComponentEvent |
isTemporary |
boolean:
true for temporary focus loss (if focus will
automatically return) |
PaintEvent |
4
methods inherited viaComponentEvent |
getGraphics |
Graphics:
Graphics object for the event |
WindowEvent |
4
methods inherited viaComponentEvent |
getWindow |
Window:
object that emitted the event |
InputEvent |
4
methods inherited via ComponentEvent |
isShiftDown |
boolean:
whether shift key is down |
isControlDown |
boolean:
whether control key is down |
isMetaDown |
boolean:
whether meta key is down |
isAltDown |
boolean:
whether alt key is down |
getWhen |
int:
millisecond timestamp for the event |
getModifiers |
int:
state of all modifiers |
isConsumed |
boolean:
whether to prevent the source from processing the event in the
normal manner |
KeyEvent |
11
methods inherited via InputEvent |
getKeyCode |
int:
key code for the event |
getKeyChar |
char:
character associated with the event |
isActionKey |
boolean:
whether key for the event is action (noncharacter) key |
MouseEvent |
11
methods inherited via InputEvent |
getX |
int:
x coordinate relative to the source object |
getY |
int:
y coordinate relative to the source object |
getPoint |
Point:
x,y location relative to the source |
getClickCount |
int:
number of mouse clicks in the event |
isPopupTrigger |
boolean:
whether the event matches native platform's popup menu trigger |
For truly simple and
local class definitions, inner classes come in an anonymous flavor
that defines a new class and creates an instance of it at the same
time. Using this option, the MouseTracker example can
be rewritten yet again:
/* using JDK 1.1: */
class Example {
public void init() {
Canvas aCanvas = ...
aCanvas.addMouseMotionListener(new MouseMotionListener() {
public void mouseDragged(MouseEvent e) {
// ... handle mouse-drag event
}
public void mouseMoved(MouseEvent e) {
// ... handle mouse-move event
}
}); /* end of aCanvas.add... statement */
// ...
}
}
This code defines an
anonymous inner class that implements the MouseMotionListener
interface with the two specified methods; it creates one instance of
that anonymous inner class; and it registers that instance as a
mouse motion listener for the canvas. The syntax takes a little
getting used to—note that the method invocation expression
beginning with "aCanvas.add..." ends several
lines later with "});".
|
|
Q . What are the different kinds of event listeners, and what are their methods?
|
Ans :
Each
concrete subclass of AWTEvent
(except PaintEvent) has a
corresponding listener interface containing one or more methods,
as described in Table 7.3.
Learning
each of the listener interfaces is the easiest way to keep track
of what events can be delivered to your application and what
methods you must define to handle the events. Table 7.3 gives the
full set of AWT listener interfaces and their methods in the JDK
1.1.
Table
: AWT Listener Interfaces and Methods—JDK 1.1
ActionListener |
actionPerformed(ActionEvent
e) |
AdjustmentListener |
adjustmentValueChanged(AdjustmentEvent
e) |
ComponentListener |
componentResized(ComponentEvent
e) |
componentMoved(ComponentEvent
e) |
componentShown(ComponentEvent
e) |
componentHidden(ComponentEvent
e) |
ContainerListener |
componentAdded(ContainerEvent
e) |
componentRemoved(ContainerEvent
e) |
FocusListener |
focusGained(FocusEvent
e) |
focusLost(FocusEvent
e) |
ItemListener |
itemStateChanged(ItemEvent
e) |
KeyListener |
keyTyped(KeyEvent
e) |
keyPressed(KeyEvent
e) |
keyReleased(KeyEvent
e) |
MouseListener |
mouseClicked(MouseEvent
e) |
mousePressed(MouseEvent
e) |
mouseReleased(MouseEvent
e) |
mouseEntered(MouseEvent
e) |
mouseExited(MouseEvent
e) |
MouseMotionListener |
mouseDragged(MouseEvent
e) |
mouseMoved(MouseEvent
e) |
TextListener |
textValueChanged(TextEvent
e) |
WindowListener |
windowOpened(WindowEvent
e) |
windowClosing(WindowEvent
e) |
windowClosed(WindowEvent
e) |
windowIconified(WindowEvent
e) |
windowDeiconified(WindowEvent
e) |
windowActivated(WindowEvent
e) |
windowDeactivated(WindowEvent
e) |
Note:
The ubiquitous boolean return type in the JDK 1.0.2
event model is nowhere to be seen in the JDK 1.1. All JDK
1.1 event-handler methods return no value (they are declared with void).
|
|
Q . When should I use an event adapter class?
|
Ans :
Use one
when it simplifies your code—the adapter classes are provided as
a convenience, not a necessity.
The
AWT event listener interfaces in the JDK 1.1 contain from
one up to seven event-handler methods. Even if you want to define
only some of the event methods belonging to an interface, your
listener object must still come from a class that implements the
whole interface. (There is no way in the Java language to
partially implement an interface.) As a convenience, the JDK 1.1
AWT -provides an event adapter class as the default implementation
for each listener interface that contains more than one method,
shown in Table.
Table
: Event Adapter Classes
| ComponentAdapter |
4
methods |
| ContainerAdapter |
2
methods |
| FocusAdapter |
2
methods |
| KeyAdapter |
3
methods |
MouseAdapter |
5
methods |
| MouseMotionAdapter |
2
methods |
| WindowAdapter |
7
methods |
Event adapters provide empty
implementations for the methods in the corresponding interface.
For instance, the JDK 1.1 source code for the MouseAdapter
class is the following:
/* in MouseAdapter.java (JDK 1.1): */
public class MouseAdapter implements MouseListener {
public void mouseClicked(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
The empty
implementations mean that events get delivered but are totally
ignored.
When you subclass from an event
adapter class, you only have to override methods for the event(s)
you wish to handle. The remaining listener methods are inherited
from the superclass. For example, to define a mouse listener class
for handling just mouse-enter and mouse-exit events, you can
define a subclass of MouseAdapter that overrides the mouseEntered
and mouseExited methods:
class MouseTracker extends MouseAdapter {
public void mouseEntered(MouseEvent e) {
// ... handle mouse-enter event
}
public void mouseExited(MouseEvent e) {
// ... handle mouse-exit event
}
Because MouseTracker
inherits from a class that implements the MouseListener
interface, it too implements the interface. ClickTracker
can define just the two methods it needs; it inherits empty
methods from MouseAdapter to ignore the rest of the
mouse events.
Event adapter classes are simply for
your convenience. You could just as well define an equivalent MouseTracker2
class without the help of MouseAdapter:
class MouseTracker2 implements MouseListener {
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {
// ... handle mouse-enter event
}
public void mouseExited(MouseEvent e) {
// ... handle mouse-exit event
}
}
|
|
Q . Do events propagate in the JDK 1.1 as they did in the older AWT event model?
|
Ans :
No; events
are sent only to the target component, and only if that component
has a registered listener for the event type.
One of the central
changes in the JDK 1.1 AWT event model is that events do not
propagate automatically from the event source up the containment
hierarchy. Instead, events are delivered only to the listeners
registered with the AWT component representing the source of the
event. To catch an event, you must register an appropriate event
listener with the specific source component.
If you want to catch events from all
components in some container, you need to write code that
recursively assigns listeners to that container's descendants. In
other words, the approach shifts from propagating events up the
tree to propagating listeners down the tree. The sample code in
the PropagateEvent11Example class provides an
illustrative implementation.
|
|
Q . Will my code written for the older JDK 1.0.2 event model still run in the JDK 1.1?
|
Ans :
Yes; the
JDK 1.1 generates JDK 1.0.2 events (and propagates them) if it can
detect that a program uses none of the JDK 1.1 event model.
Backward
compatibility with code written for JDK 1.0.2 was a strong design
goal and constraint for the JDK 1.1. The AWT event model in the
JDK 1.1 represents the most significant change from the previous
API and programming model in the JDK 1.0.2. Nevertheless, AWT
event code written exclusively for the JDK 1.0.2 can run in the
JDK 1.1 environment.
The AWT decides which events to send
based on the target component. The AWT dispatches JDK 1.1-style
events for a component if it detects any signs of the JDK 1.1
event model associated with that component (e.g., an event
listener is registered with the component). Otherwise, the AWT
dispatches JDK 1.0.2-style events for that component via the handleEvent
method, complete with propagation up the containment hierarchy.
|
|
Q . How can I create an event handling mechanism in Java?
|
Ans :
The most common mechanism for this is the callback, where one class calls the method
of another to notify it of an action or event. The class to be notified defines
methods that will respond to specific events, such as when a mouse is clicked, dragged,
or released. The AWT makes heavy use of this, with Listener interfaces.
A class implements the event handling methods of a listener, and can then be registered
with a component that generates these types of events. Classes that are event sources
provide methods which register a listener, and at a later time when the event is
generated, will invoke listener methods. The Abstract Windowing Toolkit (AWT)
and Swing APIs would be a good place to start, to see if this suits your needs.
|
|
Q . class MyOrdinaryClass must be declared abstract....It does not define void actionPerformed(java.awt.event.ActionEvent)
|
Ans
: This is one of those error messages where the compiler tries to
guess what you meant, and gives you a message based on a wrong guess!
So the message is confusing.
Your MyOrdinaryClass class implements ActionListener, which means you must include a definition of the methods from the ActionListener
interface.
But you did not. You either left a method out, or (more likely) you misspelled its name. Perhaps you wrote "ActionListener" instead of
"actionListener".
So the compiler did not find the method to fulfill the interface. Since there was a method promised but not supplied, the compiler thinks you
were aiming at an abstract class, and it prints an error message
accordingly.
|
|
|
|