Writing Event Listeners
Writing Event Listeners
This lesson gives you details about writing event listeners. You might not need to read this section.
Your first source of information for event should be the how-to section for the component in
question. You can find the appropriate section using the A Visual Guide to Swing Components (Java
Look and Feel). Each component's section shows code for handling the events most commonly
needed when implementing the component. For example, How to Use Check Boxes shows you how
to handle mouse clicks on check boxes using an item listener.
Let us look at one of the simplest event handling examples possible. It is called Beeper, and it
features a button that beeps when you click it.
Click the Launch button to run Beeper using Java™ Web Start (download JDK 6). Alternatively, to
compile and run the example yourself, consult the example index.
968
You can find the entire program in Beeper.java. Here is the code that implements the event
handling for the button:
public class Beeper ... implements ActionListener {
...
//where initialization occurs:
button.addActionListener(this);
...
public void actionPerformed(ActionEvent e) {
...//Make a beep sound...
}
}
The Beeper class implements the ActionListener interface, which contains one method:
actionPerformed. Since Beeper implements ActionListener, a Beeper object can register
as a listener for the action events that buttons fire. Once the Beeper has been registered
using the Button addActionListener method, the Beeper's actionPerformed method is
called every time the button is clicked.
The event model, which you saw at its simplest in the preceding example, is quite powerful
and flexible. Any number of event listener objects can listen for all kinds of events from any
number of event source objects. For example, a program might create one listener per
event source. Or a program might have a single listener for all events from all sources. A
program can even have more than one listener for a single kind of event from a single event
source.
Each event is represented by an object that gives information about the event and identifies the event
source. Event sources are often components or models, but other kinds of objects can also be event
sources.
Whenever you want to detect events from a particular component, first check the how-to section for
that component. A list of the component how-to sections is here. The how-to sections give examples
of handling the events that you are most likely to care about. In How to Use Color Choosers, for
instance, you will find an example of writing a change listener to track when the color changes in the
color chooser.
969
The following example demonstrates that event listeners can be registered on multiple objects and
that the same event can be sent to multiple listeners. The example contains two event sources
(JButton instances) and two event listeners. One of the event listeners (an instance of a class called
MultiListener) listens for events from both buttons. When it receives an event, it adds the event's
"action command" (which is set to the text on the button's label) to the top text area. The second
event listener (an instance of a class called Eavesdropper) listens for events on only one of the
buttons. When it receives an event, it adds the action command to the bottom text area.
Try this:
Click the Launch button to run MultiListener using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
Click the Blah blah blah button. Only the MultiListener object is registered to listen to this
button.
Click the You do not say! button. Both the MultiListener object and the Eavesdropper
object are registered to listen to this button.
You can find the entire program in MultiListener.java. Here is the code that implements
the event handling for the button:
public class MultiListener ... implements ActionListener {
...
//where initialization occurs:
button1.addActionListener(this);
button2.addActionListener(this);
button2.addActionListener(new Eavesdropper(bottomTextArea));
}
970
In the above code, both MultiListener and Eavesdropper implement the ActionListener
interface and register as action listeners using the JButton addActionListener method.
Both classes' implementations of the actionPerformed method are similar: they simply add
the event's action command to a text area.
971
Often, an event class defines methods that return information about the event. For example, you can
query a MouseEvent object for information about where the event occurred, how many clicks the
user made, which modifier keys were pressed, and so on.
Events can be divided into two groups: low-level events and semantic events. Low-level events
represent window-system occurrences or low-level input. Everything else is a semantic event.
Examples of low-level events include mouse and key events — both of which result directly from
user input. Examples of semantic events include action and item events. A semantic event might be
triggered by user input; for example, a button customarily fires an action event when the user clicks
it, and a text field fires an action event when the user presses Enter. However, some semantic events
are not triggered by low-level events, at all. For example, a table-model event might be fired when a
table model receives new data from a database.
Whenever possible, you should listen for semantic events rather than low-level events. That way,
you can make your code as robust and portable as possible. For example, listening for action events
on buttons, rather than mouse events, means that the button will react appropriately when the user
tries to activate the button using a keyboard alternative or a look-and-feel-specific gesture. When
dealing with a compound component such as a combo box, it is imperative that you stick to semantic
events, since you have no reliable way of registering listeners on all the look-and-feel-specific
components that might be used to form the compound component.
Event Adapters
Some listener interfaces contain more than one method. For example, the MouseListener interface
contains five methods: mousePressed, mouseReleased, mouseEntered, mouseExited, and
mouseClicked. Even if you care only about mouse clicks, if your class directly implements
MouseListener, then you must implement all five MouseListener methods. Methods for those
events you do not care about can have empty bodies. Here is an example:
//An example that implements a listener interface directly.
public class MyClass implements MouseListener {
...
someObject.addMouseListener(this);
...
/* Empty method definition. */
public void mousePressed(MouseEvent e) {
}
972
listener interface with more than one method. (The Listener API Table lists all the listeners and their
adapters.) For example, the MouseAdapter class implements the MouseListener interface. An
adapter class implements empty versions of all its interface's methods.
To use an adapter, you create a subclass of it and override only the methods of interest, rather than
directly implementing all methods of the listener interface. Here is an example of modifying the
preceding code to extend MouseAdapter. By extending MouseAdapter, it inherits empty definitions
of all five of the methods that MouseListener contains.
/*
* An example of extending an adapter class instead of
* directly implementing a listener interface.
*/
public class MyClass extends MouseAdapter {
...
someObject.addMouseListener(this);
...
public void mouseClicked(MouseEvent e) {
...//Event listener implementation goes here...
}
}
What if you want to use an adapter class, but do not want your public class to inherit from an adapter
class? For example, suppose you write an applet, and you want your Applet subclass to contain
some code to handle mouse events. Since the Java language does not permit multiple inheritance,
your class cannot extend both the Applet and MouseAdapter classes. A solution is to define an inner
class — a class inside of your Applet subclass — that extends the MouseAdapter class.
Inner classes can also be useful for event listeners that implement one or more interfaces directly.
//An example of using an inner class.
public class MyClass extends Applet {
...
someObject.addMouseListener(new MyAdapter());
...
class MyAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
...//Event listener implementation goes here...
}
}
}
Performance note: When considering whether to use an inner class, keep in mind that application
startup time and memory footprint are typically directly proportional to the number of classes you
load. The more classes you create, the longer your program takes to start up and the more memory it
will take. As an application developer you have to balance this with other design constraints you may
have. We are not suggesting you turn your application into a single monolithic class in hopes of
cutting down startup time and memory footprint — this would lead to unnecessary headaches and
maintenance burdens.
You can create an inner class without specifying a name — this is known as an anonymous inner
class. While it might look strange at first glance, anonymous inner classes can make your code easier
to read because the class is defined where it is referenced. However, you need to weigh the
convenience against possible performance implications of increasing the number of classes.
Here is an example of using an anonymous inner class:
//An example of using an anonymous inner class.
public class MyClass extends Applet {
...
someObject.addMouseListener(new MouseAdapter() {
973
public void mouseClicked(MouseEvent e) {
...//Event listener implementation goes here...
}
});
...
}
}
Note: One drawback of anonymous inner classes is that they can not be seen by the long-term
persistence mechanism. For more information see the API documentation for the JavaBeansTM
package and the Bean Persistence lesson in the JavaBeans trail.
Inner classes work even if your event listener needs access to private instance variables from the
enclosing class. As long as you do not declare an inner class to be static, an inner class can refer to
instance variables and methods just as if its code is in the containing class. To make a local variable
available to an inner class, just save a copy of the variable as a final local variable.
To refer to the enclosing instance, you can use EnclosingClass.this. For more information about
inner classes, see Nested Classes.
974
public void actionPerformed(ActionEvent e) {
frame.toFront();
}
});
The next simplest use of EventHandler is to extract a property value from the first argument of the
method in the listener interface (typically an event object) and use it to set the value of a property in
the target object. In the following example we create an ActionListener that sets the
nextFocusableComponent property of the target (myButton) object to the value of the "source"
property of the event.
EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent",
"source")
This would correspond to the following inner class implementation:
//Equivalent code using an inner class instead of EventHandler.
new ActionListener() {
public void actionPerformed(ActionEvent e) {
myButton.setNextFocusableComponent((Component)e.getSource());
}
}
It is also possible to create an EventHandler that just passes the incoming event object to the target's
action. If the fourth EventHandler.create argument is an empty string, then the event
is just passed along:
EventHandler.create(ActionListener.class, target, "doActionEvent", "")
This would correspond to the following inner class implementation:
//Equivalent code using an inner class instead of EventHandler.
new ActionListener() {
public void actionPerformed(ActionEvent e) {
target.doActionEvent(e);
}
}
Probably the most common use of EventHandler is to extract a property value from the source of
the event object and set this value as the value of a property of the target object. In the following
example we create an ActionListener that sets the "label" property of the target object to the value of
the "text" property of the source (the value of the "source" property) of the event.
EventHandler.create(ActionListener.class, myButton, "label", "source.text")
This would correspond to the following inner class implementation:
//Equivalent code using an inner class instead of EventHandler.
new ActionListener {
public void actionPerformed(ActionEvent e) {
myButton.setLabel(((JTextField)e.getSource()).getText());
}
}
975
Listeners that All Swing Components Support
Because all Swing components descend from the AWT Component class, you can register the
following listeners on any Swing component:
component listener
Listens for changes in the component's size, position, or visibility.
focus listener
Listens for whether the component gained or lost the keyboard focus.
key listener
Listens for key presses; key events are fired only by the component that has the current keyboard
focus.
mouse listener
Listens for mouse clicks, mouse presses, mouse releases and mouse movement into or out of the
component's drawing area.
mouse-motion listener
Listens for changes in the mouse cursor's position over the component.
mouse-wheel listener
Listens for mouse wheel movement over the component.
Hierarchy Listener
Listens for changes to a component's containment hierarchy of changed events.
Hierarchy Bounds Listener
Listens for changes to a component's containment hierarchy of moved and resized events.
All Swing components descend from the AWT Container class, but many of them are not used as
containers. So, technically speaking, any Swing component can fire container events, which notify
listeners that a component has been added to or removed from the container. Realistically speaking,
however, only containers (such as panels and frames) and compound components (such as combo
boxes) typically fire container events.
JComponent provides support for three more listener types. You can register an ancestor listener to
be notified when a component's containment ancestors are added to or removed from a container,
hidden, made visible, or moved. This listener type is an implementation detail which predated
hierarchy listeners.
The other two listener types are part of the Swing components' conformance to the JavaBeansTM
specification. Among other things, this means that Swing components support bound and constrained
properties and notify listeners of changes to the properties. Property change listeners listen for
changes to bound properties and are used by several Swing components, such as formatted text
fields, to track changes on a component's bound properties. Also, property change listeners, as well
as vetoable change listeners are used by builder tools to listen for changes on constrained properties.
For more information refer to the Properties lesson in the JavaBeans trail.
Other Listeners that Swing Components Support
The following table lists Swing components and the specialized listeners they support, not including
listeners supported by all Components, Containers, or JComponents. In many cases, the events are
fired directly from the component. In other cases, the events are fired from the component's data or
selection model. To find out the details for the particular component and listener you are interested
in, go first to the component how-to section, and then if necessary to the listener how-to section.
This table lists Swing components with their specialized listeners
Listener
Component document, list
action caret change item window other
undoable edit selection
button
976
check box
color chooser
combo box
dialog
editor pane hyperlink
file chooser
formatted text field
frame
internal frame internal frame
list list data
menu menu
menu key
menu item menu drag mouse
option pane
password field
popup menu popup menu
progress bar
radio button
slider
spinner
tabbed pane
table model
table table column model
cell editor
text area
text field
text pane hyperlink
toggle button
tree expansion
tree will expand
tree
tree model
tree selection
viewport
(used by scrollpane)
977
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
978
Let us write a simple program which displays how many number of times a button is clicked by the
user. First, here is the code that sets up the TextField , button and numClicks variable:
public class AL extends Frame implements WindowListener,ActionListener {
TextField text = new TextField(20);
Button b;
private int numClicks = 0;
In the above example, the event handler class is AL which implements ActionListener.
We would like to handle the button-click event, so we add an action listener to the button b as below:
b = new Button("Click me");
b.addActionListener(this);
In the above code, Button b is a component upon which an instance of event handler class AL is
registered.
Now, we want to display the text as to how many number of times a user clicked button. We can do
this by writing the code as below:
public void actionPerformed(ActionEvent e) {
numClicks++;
text.setText("Button Clicked " + numClicks + " times");
Now, when the user clicks the Button b, the button fires an action event which invokes the action
listener's actionPerformed method. Each time the user presses the button, numClicks variable is
appended and the message is displayed in the text field.
Here is the complete program(AL.java):
import java.awt.*;
import java.awt.event.*;
super(title);
setLayout(new FlowLayout());
addWindowListener(this);
b = new Button("Click me");
add(b);
add(text);
b.addActionListener(this);
}
979
public void windowDeactivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
More Examples: Beeper program example is available in this trail's introduction to events,
Introduction to Event Listeners. You can find the entire program in Beeper.java. The other example
described in that section, MultiListener.java, has two action sources and two action listeners,
with one listener listening to both sources and the other listening to just one.
The Action Listener API
The ActionListener Interface
Because ActionListener has only one method, it has no corresponding adapter class.
Method Purpose
actionPerformed(actionEvent) Called just after the user performs an action.
The ActionEvent Class
Method Purpose
Returns the string associated with this action. Most objects that can fire
String
action events support a method called setActionCommand that lets you
getActionCommand()
set this string.
Returns an integer representing the modifier keys the user was pressing
when the action event occurred. You can use the ActionEvent-defined
constants SHIFT_MASK, CTRL_MASK, META_MASK, and ALT_MASK to
int getModifiers() determine which keys were pressed. For example, if the user Shift-
selects a menu item, then the following expression is nonzero:
actionEvent.getModifiers() & ActionEvent.SHIFT_MASK
Object getSource()
(in Returns the object that fired the event.
java.util.EventObject)
Examples that Use Action Listeners
The following table lists some of the many examples that use action listeners.
Example Where Described Notes
Beeper This section and Contains one button with one action listener that
Introduction to Event beeps when you click the button.
Listeners
MultiListener Introduction to Event Registers two different action listeners on one button.
Listeners Also registers the same action listener on two
different buttons.
RadioButtonDemo How to Use Radio Registers the same action listener on five radio
Buttons buttons. The listener uses the getActionCommand
method to determine which radio button fired the
event.
MenuDemo How to Use Menus Shows how to listen for action events on menu items.
DragPictureDemo2 Adding Uses setActionCommand to attach the cut, copy, and
Cut/Copy/Paste paste actions to the menu. Then uses an action
Support to Data listener to forward the cut/copy/paste actions to the
Transfer currently focused component.
TextDemo How to Use Icons Loads an image in an action listener. Because loading
an image can take a while, this program uses a
980
SwingWorker to load the image in a background
thread.
TableDialogEditDemo How to Use Tables Registers an action listener through a factory method
on the OK button of a color chooser dialog.
SliderDemo How to Use Sliders Registers an action listener on a timer that controls an
animation loop.
Note: An alternate way of detecting caret changes is to attach a listener directly to the caret object
itself rather than to the text component that manages the caret. A caret fires change events (not caret
events), so you would need to write a change listener rather than a caret listener.
Here is the caret event handling code from an application called TextComponentDemo:
...
//where initialization occurs
CaretListenerLabel caretListenerLabel =
new CaretListenerLabel("Caret Status");
...
textPane.addCaretListener(caretListenerLabel);
...
protected class CaretListenerLabel extends JLabel
implements CaretListener
{
...
//Might not be invoked from the event dispatching thread.
public void caretUpdate(CaretEvent e) {
displaySelectionInfo(e.getDot(), e.getMark());
}
Note: The caretUpdate method is not guaranteed to be called in the event-dispatching thread. To
use any methods inside of caretUpdate that update the GUI special handling is required to ensure
they are executed on the event-dispatching thread. You can do this by wrapping the code inside a
Runnable and calling SwingUtilities.invokeLater on that Runnable.
981
You can find a link to the source file for TextComponentDemo in the example index for using Swing
Components. For a discussion about the caret listener aspect of the program see Listening for Caret
and Selection Changes in Text Component Features.
The Caret Listener API
The CaretListener Interface
Because CaretListener has only one method, it has no corresponding adapter class.
Method Purpose
Called when the caret in the listened-to component moves or when the
caretUpdate(CaretEvent)
selection in the listened-to component changes.
The CaretEvent Class
Method Purpose
Returns the current location of the caret. If text is selected, the caret
int getDot()
marks one end of the selection.
Returns the other end of the selection. If nothing is selected, the value
int getMark() returned by this method is equal to the value returned by getDot. Note
that the dot is not guaranteed to be less than the mark.
Object getSource()
(in Returns the object that fired the event.
java.util.EventObject)
Examples that Use Caret Listeners
The following table lists the examples that use caret listeners.
Where
Example Notes
Described
TextComponentDemo Listening for Uses a Listening Uses a Listening Uses a
Caret and listener label for Caret listener label for Caret listener label
Selection to display and to display and to display
Changes caret and Selection caret and Selection caret and
selection Changes selection Changes selection
status. status. status.
982
class SliderListener implements ChangeListener {
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider)e.getSource();
if (!source.getValueIsAdjusting()) {
int fps = (int)source.getValue();
...
}
}
}
You can find the source file for SliderDemo in the example index for Using Swing Components.
983
component's addComponentListener method. When the component's size, location, or visibility
changes, the relevant method in the listener object is invoked, and the ComponentEvent is passed to
it.
One or more component events are fired by a Component object just after the component is hidden,
made visible, moved, or resized.
The component-hidden and component-shown events occur only as the result of calls to a Component
's setVisible method. For example, a window might be miniaturized into an icon (iconified)
without a component-hidden event being fired.
To write a simple Component listener program, follow the steps mentioned below:
Declare a class which implements Component listener. For example:
public class ComponentEventDemo ... implements ComponentListener
Identify the components that you would like to catch the events for. For example: pane, label,
checkbox, etc.
Add the Component Listener to the identified components. For example:
....
label.addComponentListener(this);
.....
checkbox.addComponentListener(this);
....
panel.addComponentListener(this);
...
frame.addComponentListener(this);
Finally, catch the different events of these components by using four methods of Component
Listener as shown below:
public void componentHidden(ComponentEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Hidden");
}
}
The following example demonstrates component events. The window contains a panel that has a
label and a check box. The check box controls whether the label is visible. A text area displays a
message every time the window, panel, label, or check box fires a component event.
984
Try this:
Click the Launch button to run ComponentEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
When the window appears, one or more component-shown events have been fired.
Click the check box to hide the label.
The label fires a component-hidden event. The panel fires component-moved and component-resized
events. The check box fires a component-moved event.
Click the check box again to show the label.
The label fires a component-shown event. The panel fires component-moved and component-resized
events. The check box fires a component-moved event.
Iconify and then deiconify the window.
You do not get component-hidden or -shown events. If you want to be notified of iconification
events, you should use a window listener or a window state listener.
Resize the window.
You will see component-resized (and possibly component-moved) events from all four components
— label, check box, panel, and frame. If the frame and panel's layout manager did not make every
component as wide as possible, the panel, label, and check box would not have been resized.
You can find the demo's code in ComponentEventDemo.java. Here is just the code related to
handling component events:
public class ComponentEventDemo ... implements ComponentListener {
static JFrame frame;
JLabel label;
...
public ComponentEventDemo() {
...
JPanel panel = new JPanel(new BorderLayout());
label = new JLabel("This is a label", JLabel.CENTER);
label.addComponentListener(this);
panel.add(label, BorderLayout.CENTER);
985
...
public void componentHidden(ComponentEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Hidden");
}
986
How to Write a Container Listener
Container events are fired by a Container just after a component is added to or removed from the
container. These events are for notification only — no container listener need be present for
components to be successfully added or removed.
The following example demonstrates container events. By clicking Add a button or Remove a
button, you can add buttons to or remove them from a panel at the bottom of the window. Each time
a button is added to or removed from the panel, the panel fires a container event, and the panel's
container listener is notified. The listener displays descriptive messages in the text area at the top of
the window.
Try this:
Click the Launch button to run ContainerEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
You can find the demo's code in ContainerEventDemo.java. Here is the demo's container event
handling code:
public class ContainerEventDemo ... implements ContainerListener ... {
...//where initialization occurs:
buttonPanel = new JPanel(new GridLayout(1,1));
buttonPanel.addContainerListener(this);
...
public void componentAdded(ContainerEvent e) {
displayMessage(" added to ", e);
987
}
988
Try this:
Click the Launch button to run DocumentEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
Type in the text field at the upper left of the window or the text area beneath the text field.
One document event is fired for each character typed.
Delete text with the backspace key.
One document event is fired for each backspace key typed.
Select text and then delete it by typing backspace or by using a keyboard command such as CTRL-X
(cut).
One document event is fired for the entire deletion.
Copy text from one text component into the other using keyboard commands such as CTRL-C (copy)
and CTRL-V (paste).
One document event is fired for the entire paste operation regardless of the length of the text pasted.
If text is selected in the target text component before the paste command is issued, an additional
document event is fired because the selected text is deleted first.
You can find the demo's code in DocumentEventDemo.java. Here is the demo's document event
handling code:
public class DocumentEventDemo ... {
...//where initialization occurs:
textField = new JTextField(20);
textField.addActionListener(new MyTextActionListener());
textField.getDocument().addDocumentListener(new MyDocumentListener());
textField.getDocument().putProperty("name", "Text Field");
989
public void updateLog(DocumentEvent e, String action) {
Document doc = (Document)e.getDocument();
int changeLength = e.getLength();
displayArea.append(
changeLength + " character" +
((changeLength == 1) ? " " : "s ") +
action + doc.getProperty("name") + "." + newline +
" Text length = " + doc.getLength() + newline);
}
}
Document listeners should not modify the contents of the document; The change is already complete
by the time the listener is notified of the change. Instead, write a custom document that overrides the
insertString or remove methods, or both. See Listening for Changes on a Document for details.
The Document Listener API
The DocumentListener Interface
DocumentListener has no adapter class.
Method Purpose
Called when the style of some of the text in the listened-to
changedUpdate(DocumentEvent) document changes. This sort of event is fired only from a
StyledDocument — a PlainDocument does not fire these events.
insertUpdate(DocumentEvent) Called when text is inserted into the listened-to document.
removeUpdate(DocumentEvent) Called when text is removed from the listened-to document.
The DocumentEvent Interface
Each document event method is passed an object that implements the DocumentEvent interface.
Typically, this is an instance of DefaultDocumentEvent, defined in AbstractDocument.
Method Purpose
Returns the document that fired the event. Note that the DocumentEvent
Document
interface does not inherit from EventObject. Therefore, it does not inherit
getDocument()
the getSource method.
int getLength() Returns the length of the change.
int getOffset() Returns the location within the document of the first character changed.
Returns details about what elements in the document have changed and
ElementChange
how. ElementChange is an interface defined within the DocumentEvent
getChange(Element)
interface.
Returns the type of change that occurred. EventType is a class defined
within the DocumentEvent interface that enumerates the possible changes
EventType getType()
that can occur on a document: insert text, remove text, and change text
style.
Examples that Use Document Listeners
The following table lists the examples that use document listeners.
Where
Example Notes
Described
DocumentEventDemo This section Reports all document events that occur on the documents for
both a text field and a text area. One listener listens to both
text components and uses a client property on the document to
determine which component fired the event.
TextComponentDemo Listening for Updates a change log every time text in the listened-to
Changes on a document changes. The document in this example supports
Document styled text, so changedUpdate gets called in this example.
990
Requires this additional source file: DocumentSizeFilter
Try this:
Click the Launch button to run FocusEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
You will see a "Focus gained: JTextField" message in the text area — its "opposite component" is
null, since it is the first component to have the focus.
Click the label. Nothing happens because the label, by default, cannot get the focus.
Click the combo box. A focus-lost event is fired by the text field and a focus-gained event by the
combo box. The combo box now shows that it has the focus, perhaps with a dotted line around the
text — exactly how this is represented is look and feel dependent.
991
Notice that when the focus changes from one component to another, the first component fires a
focus-lost event before the second component fires a focus-gained event.
Select a choice from the combo box's menu. Click the combo box again. Notice that no focus event is
reported. As long as the user manipulates the same component, the focus stays on that component.
Click the text area where the focus events are printed. Nothing happens because the text area has
been rendered unclickable with setRequestFocusEnabled(false).
Click the text field to return the focus to the initial component.
Press Tab on the keyboard. The focus moves to the combo box and skips over the label.
Press Tab again. The focus moves to the button.
Click another window so that the FocusEventDemo window loses the focus. A temporary focus-lost
event is generated for the button.
Click the top of the FocusEventDemo window. A focus-gained event is fired by the button.
Press Tab on the keyboard. The focus moves to the list.
Press Tab again. The focus moves to the text area.
Notice that even though you are not allowed to click on the text area, you can tab to it. This is so
users who use assistive technologies can determine that a component is there and what it contains.
The demo disables click-to-focus for the text area, while retaining its tab-to-focus capability, by
invoking setRequestFocusEnabled(false) on the text area. The demo could use
setFocusable(false) to truly remove the text area from the focus cycle, but that would have the
unfortunate effect of making the component unavailable to those who use assistive technologies.
Press Tab again. The focus moves from the list back to the text field. You have just completed a
focus cycle. See the introduction in How to Use the Focus Subsystem for a discussion of focus
terminology and concepts.
The complete code for this demo is in the FocusEventDemo.java file. The following code snippet
represents the focus-event handling mechanism:
public class FocusEventDemo ... implements FocusListener ... {
public FocusEventDemo() {
...
JTextField textField = new JTextField("A TextField");
textField.addFocusListener(this);
...
JLabel label = new JLabel("A Label");
label.addFocusListener(this);
...
JComboBox comboBox = new JComboBox(vector);
comboBox.addFocusListener(this);
...
JButton button = new JButton("A Button");
button.addFocusListener(this);
...
JList list = new JList(listVector);
list.setSelectedIndex(1); //It's easier to see the focus change
//if an item is selected.
list.addFocusListener(this);
JScrollPane listScrollPane = new JScrollPane(list);
...
992
JScrollPane displayScrollPane = new JScrollPane(display);
...
}
...
public void focusGained(FocusEvent e) {
displayMessage("Focus gained", e);
}
993
Focus Subsystem to draw a red border around the component when it is the
current focus owner.
Try this:
Click the Launch button to run InternalFrameEventDemo using Java™ Web Start (download JDK
6). Alternatively, to compile and run the example yourself, consult the example index.
Bring up the Event Generator internal frame by clicking the Show internal frame button.
You should see an "Internal frame opened" message in the display area.
Try various operations to see what happens. For example, click the Event Generator so that it gets
activated. Click the Event Watcher so that the Event Generator gets deactivated. Click the Event
Generator's decorations to iconify, maximize, minimize, and close the window.
See How to Write Window Listeners for information on what kinds of events you will see.
994
listenedToWindow = null;
}
listenedToWindow.addInternalFrameListener(this);
...
}
}
...
}
}
The Internal Frame Listener API
995
closes it. You can use the JInternalFrame
setDefaultCloseOperation method to specify
another option, which must be either
DISPOSE_ON_CLOSE or DO_NOTHING_ON_CLOSE
(both defined in WindowConstants, an interface that
JInternalFrame implements). Or by implementing
an internalFrameClosing method in the internal
frame's listener, you can add custom behavior (such
as bringing up dialogs or saving data) to internal
frame closing.
Called just after the listened-to internal frame has
internalFrameClosed(InternalFrameEvent)
been disposed of.
internalFrameIconified(InternalFrameEvent) Called just after the listened-to internal frame is
internalFrameDeiconified(InternalFrameEvent) iconified or deiconified, respectively.
internalFrameActivated(InternalFrameEvent) Called just after the listened-to internal frame is
internalFrameDeactivated(InternalFrameEvent) activated or deactivated, respectively.
Each internal frame event method has a single parameter: an InternalFrameEvent object. The
InternalFrameEvent class defines no generally useful methods. To get the internal frame that fired
the event, use the getSource method, which InternalFrameEvent inherits from
java.util.EventObject.
Examples that Use Internal Frame Listeners
No other source files currently contain internal frame listeners. However, internal frame listeners are
very similar to WindowListeners and several Swing programs have window listeners:
Where
Example Notes
Described
InternalFrameEventDemo This section Reports all internal frame events that occur on one
internal frame to demonstrate the circumstances under
which internal frame events are fired.
DialogDemo Text CustomDialog.java uses setDefaultCloseOperation
Component instead of a window listener to determine what action to
Features take when the user closes the window.
SliderDemo How to Use Listens for window iconify and deiconify events, so that
Sliders it can stop the animation when the window is not visible.
996
label.setVisible(false);
}
}
The Item Listener API
The ItemListener Interface
Because ItemListener has only one method, it has no corresponding adapter class.
Method Purpose
itemStateChanged(ItemEvent) Called just after a state change in the listened-to component.
The ItemEvent Class
Method Purpose
Returns the component-specific object associated with the item whose
Object getItem() state changed. Often this is a String containing the text on the selected
item.
ItemSelectable Returns the component that fired the item event. You can use this instead
getItemSelectable() of the getSource method.
Returns the new state of the item. The ItemEvent class defines two
int getStateChange()
states: SELECTED and DESELECTED.
Examples that Use Item Listeners
The following table lists some examples that use item listeners.
Example Where Described Notes
ComponentEventDemo This section and How to Listens for item events on a check box, which
Write a Component determines whether a lable is visible.
Listener
CheckBoxDemo How to Use Check Four check boxes share one item listener, which
Boxes uses getItemSelected to determine which check
box fired the event.
MenuDemo How to Use Menus Listens for item events on a check box menu item.
MenuDemo How to Use Scroll Panes Listens for item events on a toggle button.
Note: To define special reactions to particular keys, use key bindings instead of a key listener. For
further information, see How to Use Key Bindings.
997
key-typed events. On the other hand, to know when the user presses the F1 key, or whether the user
pressed the '3' key on the number pad, you handle key-pressed events.
Note: To fire keyboard events, a component must have the keyboard focus.
Version note: This page reflects the focus API introduced in JDK release 1.4. As of that release, the
focus subsystem consumes focus traversal keys, such as Tab and Shift Tab. If you need to prevent
the focus traversal keys from being consumed, you can call
component.setFocusTraversalKeysEnabled(false)
on the component that is firing the key events. Your program must then handle focus traversal on its
own. Alternatively, you can use the KeyEventDispatcher class to pre-listen to all key events. The
focus page has detailed information on the focus subsystem.
You can obtain detailed information about a particular key-pressed event. For example, you can
query a key-pressed event to determine if it was fired from an action key. Examples of action keys
include Copy, Paste, Page Up, Undo, and the arrow and function keys. As of JDK release 1.4, you
can also query a key-pressed or key-released event to determine the location of the key that fired the
event. Most key events are fired from the standard keyboard, but the events for some keys, such as
Shift, have information on whether the user pressed the Shift key on the left or the right side of the
keyboard. Likewise, the number '2' can be typed from either the standard keyboard or from the
number pad.
For key-typed events you can obtain the key character value as well as any modifiers used.
Note: You should not rely on the key character value returned from getKeyChar unless it is involved
in a key-typed event.
The following example demonstrates key events. It consists of a text field that you can type into,
followed by a text area that displays a message every time the text field fires a key event. A button at
the bottom of the window lets you clear both the text field and text area.
Try this:
998
Click the Launch button to run KeyEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
Type a lowercase 'a' by pressing and releasing the A key on the keyboard.
The text field fires three events: a key-pressed event, a key-typed event, and a key-released event.
Note that the key-typed event doesn't have key code information, and key-pressed and key-released
events don't have key character information. None of the events so far are from modifier or action
keys and the key location, reported on the key-pressed and key-released events, is most likely
standard.
Press the Clear button.
You might want to do this after each of the following steps.
Press and release the Shift key.
The text field fires two events: a key-pressed and a key-released. The text field doesn't fire a key-
typed event because Shift, by itself, doesn't correspond to any character.
Type an uppercase 'A' by pressing the Shift and A keys.
You'll see the following events, although perhaps not in this order: key-pressed (Shift), key-pressed
(A), key typed ('A'), key-released (A), key-released (Shift). Note that Shift is listed as the modifier
key for the key-typed and key-pressed events.
Type an uppercase 'A' by pressing and releasing the Caps Lock key, and then pressing the A key.
You should see the following events: key-pressed (Caps Lock), key-pressed (A), key typed ('A'),
key-released (A). Note that Caps Lock is not listed as a modifier key.
Press the Tab key. No Tab key-pressed or key-released events are received by the key event listener.
This is because the focus subsystem consumes focus traversal keys, such as Tab and Shift Tab. Press
Tab twice more to return the focus to the text area.
Press a function key, such as F3. You'll see that the function key is an action key.
Press the left Shift key, followed by the right Shift key. The key-pressed and key-released events
indicate which Shift key was typed.
Press the Num Lock key if your keyboard has a number pad.
As for Caps Lock, there is a key-pressed event, but no key-released event.
Press the '2' key on the number pad. You see the key-pressed, key-typed, and key-released events for
the number '2'.
Press the '2' key on the standard keyboard. Again, you see the three event messages. The key-typed
events for both number 2 keys are identical. But the key-pressed and key-released events indicate
different key codes and different key locations.
Press the Num Lock key again. A key-released event is fired.
You can find the example's code in KeyEventDemo.java. Here is the demo's key event handling
code:
public class KeyEventDemo ... implements KeyListener ... {
...//where initialization occurs:
typingArea = new JTextField(20);
typingArea.addKeyListener(this);
999
/** Handle the key-pressed event from the text field. */
public void keyPressed(KeyEvent e) {
displayInfo(e, "KEY PRESSED: ");
}
1000
The Key Listener API
1001
Examples that Use Key Listeners
The following table lists the examples that use key listeners.
Where
Example Notes
Described
KeyEventDemo This section Reports all key events that occur on a text field to demonstrate the
circumstances under which key events are fired.
Note: Combo box models also fire list data events. However, you normally do not need to know
about them unless you are creating a custom combo box model.
Try this:
Click the Launch button to run ListDataEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
Type in the name of your favorite ski resort and click the Add button. An intervalAdded event was
fired.
Select a few continguous items in the list and click the Delete button. An intervalRemoved event
was fired.
1002
Select one item and move it up or down in the list with the arrow buttons. Two contentsChanged
events are fired — one for the item that moved and one for the item that was displaced.
You can find the demo's code in ListDataEventDemo.java. Here is the code that registers a list data
listener on the list model and implements the listener:
//...where member variables are declared...
private DefaultListModel listModel;
...
//Create and populate the list model
listModel = new DefaultListModel();
...
listModel.addListDataListener(new MyListDataListener());
1003
How to Write a List Selection Listener
List selection events occur when the selection in a list or table is either changing or has just changed.
List selection events are fired from an object that implements the ListSelectionModel interface. To
get a table's list selection model object, you can use either getSelectionModel method or
getColumnModel().getSelectionModel().
To detect list selection events, you register a listener on the appropriate list selection model object.
The JList class also gives you the option of registering a listener on the list itself, rather than
directly on the list selection model.
This section looks at two examples that show how to listen to list selection events on a selection
model. Examples that Use List Selection Listeners lists examples that listen on the list directly.
In these two examples, you can dynamically change the selection mode to any of the three supported
modes:
single selection mode
single interval selection mode
multiple interval selection mode
Here is a picture of ListSelectionDemo example running in a List :
Try this:
Click the Launch button to run ListSelectionDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
Select and deselect items in the list. The mouse and keyboard commands required to select items
depends on the look and feel. For the Java look and feel, click the left mouse button to begin a
selection, use the shift key to extend a selection contiguously, and use the control key to extend a
selection discontiguously. Note that there are two types of selections: Lead and Anchor. Lead is the
focused item and Anchor is the highlighted item. When you press ctrl key and move up and down,
the lead selection causes the events being fired even though the actual selection has not changed.
Dragging the mouse moves or extends the selection, depending on the list selection mode.
1004
Try this:
Click the Launch button to run TableListSelectionDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
Select and deselect items in the table. The mouse and keyboard commands required to select items
depends on the look and feel. For the Java look and feel, click the left mouse button to begin a
selection, use the shift key to extend a selection contiguously, and use the control key to extend a
selection discontiguously. Note that there are two types of selections: Lead and Anchor. Lead is the
focused item and Anchor is the highlighted item. When you press ctrl key and move up or down, the
lead selection causes the events being fired even though the actual selection has not changed.
Dragging the mouse moves or extends the selection, depending on the list selection mode.
You can find the entire program of ListSelectionDemo in ListSelectionDemo.java and the entire
program of TableListSelectionDemo in TableListSelectionDemo.java.
Here is the code from ListSelectionDemo that sets up the selection model and adds a listener to it:
...//where the member variables are defined
JList list;
...//in the init method:
listSelectionModel = list.getSelectionModel();
listSelectionModel.addListSelectionListener(
new SharedListSelectionHandler());
...
And here is the code for the listener, which works for all the possible selection modes:
class SharedListSelectionHandler implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
if (lsm.isSelectionEmpty()) {
output.append(" <none>");
} else {
// Find out which indexes are selected.
1005
int minIndex = lsm.getMinSelectionIndex();
int maxIndex = lsm.getMaxSelectionIndex();
for (int i = minIndex; i <= maxIndex; i++) {
if (lsm.isSelectedIndex(i)) {
output.append(" " + i);
}
}
}
output.append(newline);
}
}
This valueChanged method displays the first and last indices reported by the event, the value of the
event's isAdjusting flag, and the indices currently selected.
Note that the first and last indices reported by the event indicate the inclusive range of items for
which the selection has changed. If the selection mode is multiple interval selection some items
within the range might not have changed. The isAdjusting flag is true if the user is still
manipulating the selection, and false if the user has finished changing the selection.
The ListSelectionEvent object passed into valueChanged indicates only that the selection has
changed. The event contains no information about the current selection. So, this method queries the
selection model to figure out the current selection.
1006
Examples that Use List Selection Listeners
The following table lists the examples that use list selection listeners.
Where
Example Notes
Described
ListSelectionDemo This section Reports all list selection events that occur on a list. Lets
the user dynamically change the selection mode.
TableListSelectionDemo This section Reports all list selection events that occur on a table.
Lets the user dynamically change the selection mode.
ListDemo How to Use Listens to events on a single-selection list (not on its
Lists selection model). Enables and disables a button
depending on whether any items are selected in the list.
SplitPaneDemo How to Use Listens to events on a single-selection list (not on its
Lists selection model).
SimpleTableSelectionDemo How to Use Uses two different list selection listeners on one table.
Tables One listener listens to list selection events on table
columns, the other listens to list selection events on table
rows.
1007
Try this:
Click the Launch button to run MouseEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
Move the cursor into the yellow rectangle at the top of the window.
You will see one or more mouse-entered events.
Press and hold the left mouse button without moving the mouse.
You will see a mouse-pressed event. You might see some extra mouse events, such as mouse-exited
and then mouse-entered.
Release the mouse button.
You will see a mouse-released event. If you did not move the mouse, a mouse-clicked event will
follow.
Press and hold the mouse button again, and then drag the mouse so that the cursor ends up outside
the window. Release the mouse button.
You will see a mouse-pressed event, followed by a mouse-exited event, followed by a mouse-
released event. You are not notified of the cursor's motion. To get mouse-motion events, you need to
implement a mouse-motion listener.
You can find the demo's code in MouseEventDemo.java and BlankArea.java. Here is the demo's
mouse event handling code:
public class MouseEventDemo ... implements MouseListener {
//where initialization occurs:
//Register for mouse events on blankArea and the panel.
blankArea.addMouseListener(this);
addMouseListener(this);
...
1008
public void mouseEntered(MouseEvent e) {
saySomething("Mouse entered", e);
}
1009
following constants is returned: NOBUTTON, BUTTON1, BUTTON2, or
BUTTON3. Introduced in release 1.4.
Returns true if the mouse event should cause a popup menu to
appear. Because popup triggers are platform dependent, if your
program uses popup menus, you should call isPopupTrigger for all
boolean isPopupTrigger()
mouse-pressed and mouse-released events fired by components over
which the popup can appear. See Bringing Up a Popup Menu for more
information about popup menus.
Returns a String describing the modifier keys and mouse buttons that
String were active during the event, such as "Shift", or "Ctrl+Shift". These
getMouseModifiersText(int) strings can be localized using the awt.properties file. Introduced in
release 1.4.
The InputEvent Class
The MouseEvent class inherits many useful methods from InputEvent and a couple handy methods
from the ComponentEvent and AWTEvent classes.
Method Purpose
Returns the event type, which defines the particular action. For example,
int getID() the MouseEvent id reflects the state of the mouse buttons for every mouse
(in event. The following states could be specified by the MouseEvent id:
java.awt.AWTEvent) MouseEvent.MOUSE_PRESSED, MouseEvent.MOUSE_RELEASED, and
MouseEvent.MOUSE_CLICKED.
Component
Returns the component that fired the event. You can use this method
getComponent()
instead of the getSource method.
(in ComponentEvent)
Returns the timestamp of when this event occurred. The higher the
int getWhen()
timestamp, the more recently the event occurred.
boolean isAltDown()
boolean
Return the state of individual modifier keys at the time the event was
isControlDown()
fired.
boolean isMetaDown()
boolean isShiftDown()
Returns the state of all the modifier keys and mouse buttons when the
event was fired. You can use this method to determine which mouse
button was pressed (or released) when a mouse event was fired. The
InputEvent class defines these constants for use with the getModifiers
int getModifiers() method: ALT_MASK, BUTTON1_MASK, BUTTON2_MASK, BUTTON3_MASK,
CTRL_MASK, META_MASK, and SHIFT_MASK. For example, the following
expression is true if the right button was pressed:
(mouseEvent.getModifiers() & InputEvent.BUTTON3_MASK)
== InputEvent.BUTTON3_MASK
Returns the extended modifier mask for this event. Extended modifiers
represent the state of the mouse button and all modal keys, such as ALT,
CTRL, META, just after the event occurred. You can check the status of
the modifiers using one of the following predefined bitmasks:
int getModifiersEx()
SHIFT_DOWN_MASK, CTRL_DOWN_MASK, META_DOWN_MASK,
ALT_DOWN_MASK, BUTTON1_DOWN_MASK, BUTTON2_DOWN_MASK,
BUTTON3_DOWN_MASK, or ALT_GRAPH_DOWN_MASK. For example, to check
that button 1 is down, but that buttons 2 and 3 are up, you would use the
1010
following code snippet:
if (event.getModifiersEx() & (BUTTON1_DOWN_MASK |
BUTTON2_DOWN_MASK |
BUTTON3_DOWN_MASK)
== BUTTON1_DOWN_MASK) {
...
}
Introduced in release 1.4.
Returns a string describing the extended modifier keys and mouse
int
buttons, such as "Shift", "Button1", or "Ctrl+Shift". These strings can be
getModifiersExText(int)
localized by changing the awt.properties file. Introduced in release 1.4.
1011
Alternatively, use the corresponding MouseAdapter AWT class, which implements the
MouseMotionListener interface, to create a MouseMotionEvent and override the
methods for the specific events.
The following demo code contains a mouse-motion listener. This demo is exactly the same as the
demo described in the How to Write a Mouse Listener section, except for substituting the
MouseMotionListener interface for the MouseListener interface. Additionally,
MouseMotionEventDemo implements the mouseDragged and mouseMoved methods instead of the
mouse listener methods, and displays coordinates instead of numbers of clicks.
Try this:
Click the Launch button to run MouseMotionEventDemo using Java™ Web Start (download JDK
6). Alternatively, to compile and run the example yourself, consult the example index.
Move the cursor into the yellow rectangle at the top of the window.
You will see one or more mouse-moved events.
Press and hold the mouse button, and then move the mouse so that the cursor is outside the yellow
rectangle.
You will see mouse-dragged events.
You can find the demo's code in MouseMotionEventDemo.java and BlankArea.java. The
following code snippet from MouseMotionEventDemo implements the mouse-motion event handling:
public class MouseMotionEventDemo extends JPanel
implements MouseMotionListener {
//...in initialization code:
//Register for mouse events on blankArea and panel.
blankArea.addMouseMotionListener(this);
addMouseMotionListener(this);
...
}
1012
saySomething("Mouse dragged", e);
}
void updateSize(MouseEvent e) {
int x = e.getX();
int y = e.getY();
currentRect.setSize(x - currentRect.x,
y - currentRect.y);
updateDrawableRect(getWidth(), getHeight());
Rectangle totalRepaint = rectToDraw.union(previouseRectDrawn);
repaint(totalRepaint.x, totalRepaint.y,
totalRepaint.width, totalRepaint.height);
}
}
The Mouse-Motion Listener API
1013
that component.
Called in response to the user moving the mouse with no mouse
mouseMoved(MouseEvent) buttons pressed. This event is fired by the component that's currently
under the cursor.
Each mouse-motion event method has a single parameter — and it's not called MouseMotionEvent!
Instead, each mouse-motion event method uses a MouseEvent argument. See The MouseEvent API
for information about using MouseEvent objects.
1014
platform dependent. Both the type and amount of scrolling can be set via the mouse control panel for
the platform.
The following example demonstrates mouse-wheel events.
Try this:
Click the Launch button to run MouseWheelEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
The output from MouseWheelEventDemo for a system that uses unit increments for its mouse wheel
might look as follows:
javax.swing.JTextArea: Mouse wheel moved UP 1 notch(es)
Scroll type: WHEEL_UNIT_SCROLL
Scroll amount: 3 unit increments per notch
Units to scroll: -3 unit increments
Vertical unit increment: 16 pixels
The scroll amount, returned by the getScrollAmount method, indicates how many units will be
scrolled and always presents a positive number. The units to scroll, returned by the
getUnitsToScroll method, are positive when scrolling down and negative when scrolling up. The
number of pixels for the vertical unit is obtained from the vertical scroll bar using the
getUnitIncrement method. In the preceding example, rolling the mouse wheel one notch upward
should result in the text area scrolling upward 48 pixels (3x16).
For a system that uses block increments for mouse-wheel scrolling, for the same movement of the
mouse wheel the output might look as follows:
javax.swing.JTextArea: Mouse wheel moved UP 1 notch(es)
Scroll type: WHEEL_BLOCK_SCROLL
Vertical block increment: 307 pixels
1015
The vertical block increment is obtained from the vertical scroll bar using the getBlockIncrement
method. In this case, rolling the mouse wheel upward one notch means that the text area should
scroll upward 307 pixels.
Find the demo's code in the MouseWheelEventDemo.java file. The following code snippet is related
to the mouse-wheel event handling:
public class MouseWheelEventDemo ... implements MouseWheelListener ... {
public MouseWheelEventDemo() {
//where initialization occurs:
//Register for mouse-wheel events on the text area.
textArea.addMouseWheelListener(this);
...
}
1016
Returns the number of notches the mouse wheel was rotated. If the mouse
int
wheel rotated towards the user (down) the value is positive. If the mouse wheel
getWheelRotation()
rotated away from the user (up) the value is negative.
Returns the number of units that should be scrolled per notch. This is always a
int
positive number and is only valid if the scroll type is
getScrollAmount()
MouseWheelEvent.WHEEL_UNIT_SCROLL.
int Returns the positive or negative units to scroll for the current event. This is
getUnitsToScroll() only valid when the scroll type is MouseWheelEvent.WHEEL_UNIT_SCROLL.
Examples That Use Mouse Wheel Listeners
The following table lists the examples that use mouse-wheel listeners.
Where
Example Notes
Described
MouseWheelEventDemo This section Reports all mouse wheel events that occur within a text area to
demonstrate the circumstances under which mouse wheel
events are fired.
1017
focusManager.addPropertyChangeListener(new FocusManagerListener());
...
public FocusManagerListener() implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if ("focusOwner".equals(propertyName) {
...
} else if ("focusedWindow".equals(propertyName) {
...
}
}
...
}
The second way to register a property change listener uses the method
addPropertyChangeListener(String, PropertyChangeListener). The String argument is the
name of a property. Using this method means that you only receive notification when a change
occurs to that particular property. So, for example, if you registered a property change listener like
this:
aComponent.addPropertyChangeListener("font",
new FontListener());
FontListener only receives notification when the value of the component's font property changes. It
does not receive notification when the value changes for transferHandler, opaque, border, or any
other property.
The following example shows how to register a property change listener on the value property of a
formatted text field using the two-argument version of addPropertyChangeListener:
//...where initialization occurs:
double amount;
JFormattedTextField amountField;
...
amountField.addPropertyChangeListener("value",
new FormattedTextFieldListener());
...
class FormattedTextFieldListener implements PropertyChangeListener {
public void propertyChanged(PropertyChangeEvent e) {
Object source = e.getSource();
if (source == amountField) {
amount = ((Number)amountField.getValue()).doubleValue();
...
}
...//re-compute payment and update field...
}
}
Registering a PropertyChangeListener
Method Purpose
Add a property-change listener to the
addPropertyChangeListener(PropertyChangeListener)
listener list.
Add a property-change listener for a
addPropertyChangeListener(String, specific property. The listener is called only
PropertyChangeListener) when there is a change to the specified
property.
The PropertyChangeListener Interface
Because PropertyChangeListener has only one method, it has no corresponding adapter class.
Method Purpose
1018
propertyChange(PropertyChangeEvent) Called when the listened-to bean changes a bound property.
The PropertyChangeEvent Class
Method Purpose
Object getNewValue()
Return the new, or old, value of the property, respectively.
Object getOldValue()
String getPropertyName() Return the name of the property that was changed.
void setPropagationId() Get or set the propagation ID value. Reserved for future use.
The following table lists the examples that use property-change listeners.
Where
Example Notes
Described
FormattedTextFieldDemo How to Use A property-change listener is registered on several
Formatted Text formatted text fields to track changes to the value
Fields property.
DialogDemo How to Make The CustomDialog class registers a property-change
Dialogs listener on an option pane to listen to the value and
inputValue properties.
FileChooserDemo2 How to Use File The ImagePreview class registers a property-change
Choosers listener on the file chooser to listen to the
directoryChanged and selectedFileChanged properties.
TrackFocusDemo How to Use the A property-change listener is registered on the
Focus keyboard focus manager to track changes to the
Subsystem focusOwner property.
1019
(in
java.util.EventObject)
Return the index of the first row that changed.
int getFirstRow()
TableModelEvent.HEADER_ROW specifies the table header.
int getLastRow() The last row that changed. Again, HEADER_ROW is a possible value.
Return the index of the column that changed. The constant
int getColumn() TableModelEvent.ALL_COLUMNS specifies that all the columns might
have changed.
What happened to the changed cells. The returned value is one of the
int getType() following: TableModelEvent.INSERT, TableModelEvent.DELETE, or
TableModelEvent.UPDATE.
This example demonstrates a simple tree expansion listener. The text area at the bottom of the
window displays a message every time a tree expansion event occurs. It's a straightforward, simple
demo. To see a more interesting version that can veto expansions, see How to Write a Tree-Will-
Expand Listener.
1020
Try this:
Click the Launch button to run TreeExpandEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
The following code shows how the program handles expansion events. You can find the source code
for this example in TreeExpandEventDemo.java.
public class TreeExpandEventDemo ... {
...
void saySomething(String eventDescription, TreeExpansionEvent e) {
textArea.append(eventDescription + "; "
+ "path = " + e.getPath()
+ newline);
}
1021
The TreeExpansionEvent API
Method Purpose
Object
Return the object that fired the event.
getSource()
TreePath Returns a TreePath object that identifies each node from the root of the tree to the
getPath() collapsed/expanded node, inclusive.
Examples that Use Tree Expansion Listeners
The following table lists the examples that use tree expansion listeners.
Example Where Described Notes
TreeExpandEventDemo This section Displays a message whenever a tree
expansion event occurs.
TreeExpandEventDemo2 How to Write a Tree-Will- Adds a tree-will-expand listener to
Expand Listener TreeExpandEventDemo.
1022
Examples that Use Tree Model Listeners
The following table lists the examples that use tree expansion listeners.
Where
Example Notes
Described
DynamicTreeDemo How to Use The DynamicTree class implements a tree model listener to detect
Trees when the user has edited a node's data.
/* if nothing is selected */
if (node == null) return;
1023
getOldLeadSelectionPath()
TreePath getPath() Return the first path element.
Return the paths that have been added or removed from the
TreePath[] getPaths()
selection.
Return true if the first path element has been added to the
boolean isAddedPath() selection. Returns false if the first path has been removed from
the selection.
Return true if the path specified by the index was added to the
boolean isAddedPath(int)
selection.
boolean isAddedPath(TreePath) Return true if the specified path was added to the selection.
Object Return the last path component in the first node of the current
getLastSelectedPathComponent() selection.
TreePath getLeadSelectionPath()
Return the current lead path.
(in JTree)
This demo adds a tree-will-expand listener to the TreeExpandEventDemo example discussed in How
to Write a Tree Expansion Listener. The code added here demonstrates that tree-will-expand listeners
prevent node expansions and collapses: The listener will prompt you for confirmation each time you
try to expand a node.
Try this:
Click the Launch button to run TreeExpandEventDemo2 using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
1024
Click the graphic to the left of the Potrero Hill node. This tells the tree that you want to expand the
node.
A dialog appears asking you whether you really want to expand the node.
Click "Expand" or dismiss the dialog.
Messages in the text area tell you that both a tree-will-expand event and a tree-expanded event have
occurred. At the end of each message is the path to the expanded node.
Try to expand another node, but this time press the "Cancel Expansion" button in the dialog.
The node does not expand. Messages in the text area tell you that a tree-will-expand event occurred,
and that you cancelled a tree expansion.
Collapse the Potrero Hill node.
The node collapses without a dialog appearing, because the event handler's treeWillCollapse
method lets the collapse occur, uncontested.
The following snippet shows the code that this program adds to TreeExpandEventDemo. The bold
line prevents the tree expansion from happening. You can find all the demo's source code in
TreeExpandEventDemo2.java.
public class TreeExpandEventDemo2 ... {
...
class DemoArea ... implements ... TreeWillExpandListener {
...
public DemoArea() {
...
tree.addTreeWillExpandListener(this);
...
}
...
//Required by TreeWillExpandListener interface.
public void treeWillExpand(TreeExpansionEvent e)
throws ExpandVetoException {
saySomething("Tree-will-expand event detected", e);
//...show a dialog...
if (/* user said to cancel the expansion */) {
//Cancel expansion.
saySomething("Tree expansion cancelled", e);
throw new ExpandVetoException(e);
}
}
1025
method should throw a ExpandVetoException event.
See The Tree Expansion Event API for information about the TreeExpansionEvent argument for
the preceding methods.
1026
Examples that Use Undoable Edit Listeners
The following table lists the examples that use undoable edit listeners.
Example Where Described Notes
TextComponentDemo Implementing Undo Implements undo and redo on a text pane with help
and Redo from an undoable edit listener.
Version note: Prior to JDK release 1.4, focus-gained and focus-lost events were inferred by using
the WindowListener methods windowActivated and windowDeactivated. This approach did not
work with windows that were not frames or dialogs, because such windows never received those
events. To determine a window's iconification, the ComponentListener methods componentHidden
and componentShown were used. As of JDK release 1.4, the methods defined in
WindowFocusListener and WindowStateListener are preferred.
While you can use the WindowListener methods to detect some window states, such as
iconification, there are two reasons why a WindowStateListener might be preferable: it has only
one method for you to implement, and it provides support for maximization.
Note: Not all window managers/native platforms support all window states. The 1.4
java.awt.Toolkit method isFrameStateSupported(int) can be used to determine whether a
1027
particular window state is supported by a particular window manager. The WindowEventDemo
example, described later in this section, shows how this method can be used.
Window listeners are commonly used to implement custom window-closing behavior. For example,
a window listener is used to save data before closing the window, or to exit the program when the
last window closes.
A user does not necessarily need to implement a window listener to specify what a window should
do when the user closes it. By default, when the user closes a window the window becomes invisible.
To specify different behavior, use the setDefaultCloseOperation method of the JFrame or
JDialog classes. To implement a window-closing handler, use the
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE) method to enable the
window listener to provide all window-closing duties. See Responding to Window-Closing Events
for details on how to use setDefaultCloseOperation.
Version note: As of JDK release 1.4, when the last displayable window within the Java virtual
machine (VM) is disposed of, the VM may terminate. In previous releases, such as 1.3, the VM
remained running even if all windows were disposed of. Note, however, that there can be a delay
before the program exits automatically, and that under some circumstances the program might keep
running. It is quicker and safer to explicitly exit the program using System.exit(int). See AWT
Threading Issues for more information.
Window listeners are also commonly used to stop threads and release resources when a window is
iconified, and to start up again when the window is deiconified. This avoids unnecessarily using the
processor or other resources. For example, when a window that contains animation is iconified, it
should stop its animation thread and free any large buffers. When the window is deiconified, it can
start the thread again and recreate the buffers.
The following example demonstrates window events. A non-editable text area reports all window
events that are fired by its window. This demo implements all methods in the WindowListener,
WindowFocusListener, and WindowStateListener interfaces. You can find the demo's code in
WindowEventDemo.java.
1028
Try this:
Click the Launch button to run WindowEventDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.
When the window appears, several messages are already displayed. One line reports whether your
window manager supports MAXIMIZED_BOTH. If the window manager does not support other
window states, this condition is also reported. Next, several lines are displayed, reporting that the
window's window listener has received window-opened, activated, and gained-focus events. All the
messages displayed in the window are also sent to standard output.
Click another window. The "window lost focus" and "window deactivated" messages will be
displayed. If this window is not a frame or a dialog, it will receive the activated or deactivated
events.
Click the WindowEventDemo window. You'll see "window activated" and "window gained focus"
messages.
Iconify the window, using the window controls. Two iconification messages are displayed, one from
the window listener and the other from the window state listener. Unless you are looking at standard
output, the messages will not display until the window is deiconified. Window-deactivation and
window-lost-focus events are also reported.
De-iconify the window. Two deiconification messages are displayed, one from the window listener
and the other from the window state listener. The windowStateChanged method in
WindowStateListener class gives the same information that you get using the windowIconified
and windowDeiconified methods in WindowListener class. Window-activation and window-
gained-focus events are also reported.
Maximize the window, if your look and feel provides a way to do so. Note that some look and feels
running on some window managers, such as the Java look and feel on dtwm, provide a way to
1029
maximize the window, but no events are reported. This is because dtwm mimics maximization by
resizing the window, but it is not a true maximization event. Some look and feels provide a way to
maximize the window in the vertical or horizontal direction only. Experiment with your window
controls to see what options are available.
Close the window, using the window controls. A window closing message is displayed. Once the
window has closed, a window closed message is sent to standard output.
addWindowListener(this);
addWindowFocusListener(this);
addWindowStateListener(this);
checkWM();
}
1030
public void windowClosing(WindowEvent e) {
displayMessage("WindowListener method called: windowClosing.");
//A pause so user can see the message before
//the window actually closes.
ActionListener task = new ActionListener() {
boolean alreadyDisposed = false;
public void actionPerformed(ActionEvent e) {
if (frame.isDisplayable()) {
alreadyDisposed = true;
frame.dispose();
}
}
};
Timer timer = new Timer(500, task); //fire every half second
timer.setInitialDelay(2000); //first delay 2 seconds
timer.setRepeats(false);
timer.start();
}
1031
int oldState = e.getOldState();
String msg = prefix
+ newline + space
+ "New state: "
+ convertStateToString(state)
+ newline + space
+ "Old state: "
+ convertStateToString(oldState);
displayMessage(msg);
}
The window listener API consists of three window listener interfaces and the WindowEvent class.
Their methods are listed in the following tables:
The WindowListener Interface
The WindowFocusListener Interface
The WindowStateListener Interface
The WindowEvent Class
The methods from all three interfaces are available through the WindowAdapter class.
The WindowListener Interface
Method Purpose
Called just after the listened-to window has been shown for the
windowOpened(WindowEvent)
first time.
Called in response to a user request for the listened-to window
windowClosing(WindowEvent) to be closed. To actually close the window, the listener should
invoke the window's dispose or setVisible(false) method.
windowClosed(WindowEvent) Called just after the listened-to window has closed.
windowIconified(WindowEvent) Called just after the listened-to window is iconified or
1032
windowDeiconified(WindowEvent) deiconified, respectively.
Called just after the listened-to window is activated or
deactivated, respectively. These methods are not sent to
windowActivated(WindowEvent)
windows that are not frames or dialogs. For this reason, we
windowDeactivated(WindowEvent)
prefer the 1.4 windowGainedFocus and windowLostFocus
methods to determine when a window gains or loses the focus.
The WindowFocusListener Interface
Method Purpose
windowGainedFocus(WindowEvent) Called just after the listened-to window gains or loses the
windowLostFocus(WindowEvent) focus, respectively.
The WindowStateListener Interface
Method Purpose
Called just after the listened-to window's state is changed by
being iconified, deiconified, maximized, or returned to
normal. The state is available through the WindowEvent as a
bitwise mask. The possible values, defined in
java.awt.Frame, are:
NORMAL. Indicates that no state bits are set.
ICONIFIED.
windowStateChanged(WindowEvent) MAXIMIZED_HORIZ.
MAXIMIZED_VERT.
MAXIMIZED_BOTH. Concatenates MAXIMIZED_HORIZ and
MAXIMIZED_VERT. A window manager may support
MAXIMIZED_BOTH, while not supporting MAXIMIZED_HORIZ or
MAXIMIZED_VERT. The java.awt.Toolkit method
isFrameStateSupported(int) can be used to determine
what states are supported by the window manager.
1033
Examples that Use Window Listeners
The following table lists the examples that use window listeners.
Example Where Notes
Described
WindowEventDemo This section Reports all window events that occur on one window to
demonstrate the circumstances under which window
events are fired.
SliderDemo How to Use Listens for window iconify and deiconify events, so that
Sliders it can stop the animation when the window isn't visible.
InternalFrameEventDemo How to Write Reports all internal frame events that occur on one
an Internal internal frame to demonstrate the circumstances under
Frame Listener which internal frame events are fired. Internal frame
events are similar to window events.
DialogDemo Text CustomDialog.java uses
Component setDefaultCloseOperation instead of a window
Features listener to determine what action to take when the user
closes the window.
Framework — A demo that allows multiple windows to be created and
destroyed.
1034
removeUpdate(DocumentEvent)
ExceptionListener none exceptionThrown(Exception)
focusGained(FocusEvent)
FocusListener FocusAdapter
focusLost(FocusEvent)
HierarchyBoundsListen HierarchyBoundsAdap ancestorMoved(HierarchyEvent)
er ter ancestorResized(HierarchyEvent)
HierarchyListener none hierarchyChanged(HierarchyEvent)
HyperlinkListener none hyperlinkUpdate(HyperlinkEvent)
caretPositionChanged(InputMethodEvent)
InputMethodListener none inputMethodTextChanged(InputMethodEven
t)
internalFrameActivated(InternalFrameEv
ent)
internalFrameClosed(InternalFrameEvent
)
internalFrameClosing(InternalFrameEven
t)
InternalFrameAdapte internalFrameDeactivated(InternalFrame
InternalFrameListener
r Event)
internalFrameDeiconified(InternalFrame
Event)
internalFrameIconified(InternalFrameEv
ent)
internalFrameOpened(InternalFrameEvent
)
ItemListener none itemStateChanged(ItemEvent)
keyPressed(KeyEvent)
KeyListener KeyAdapter keyReleased(KeyEvent)
keyTyped(KeyEvent)
contentsChanged(ListDataEvent)
ListDataListener none intervalAdded(ListDataEvent)
intervalRemoved(ListDataEvent)
ListSelectionListener none valueChanged(ListSelectionEvent)
menuDragMouseDragged(MenuDragMouseEven
t)
menuDragMouseEntered(MenuDragMouseEven
t)
MenuDragMouseListener none
menuDragMouseExited(MenuDragMouseEvent
)
menuDragMouseReleased(MenuDragMouseEve
nt)
menuKeyPressed(MenuKeyEvent)
MenuKeyListener none menuKeyReleased(MenuKeyEvent)
menuKeyTyped(MenuKeyEvent)
menuCanceled(MenuEvent)
MenuListener none menuDeselected(MenuEvent)
menuSelected(MenuEvent)
mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
MouseInputListener mouseExited(MouseEvent)
(extends MouseListener MouseInputAdapter mousePressed(MouseEvent)
and MouseAdapter mouseReleased(MouseEvent)
MouseMotionListener mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
MouseAdapter(MouseEvent)
1035
mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
MouseListener MouseAdapter, mouseExited(MouseEvent)
MouseInputAdapter mousePressed(MouseEvent)
mouseReleased(MouseEvent)
columnAdded(TableColumnModelEvent)
columnMoved(TableColumnModelEvent)
TableColumnModelListe columnRemoved(TableColumnModelEvent)
ner none columnMarginChanged(ChangeEvent)
columnSelectionChanged(ListSelectionEv
ent)
TableModelListener none tableChanged(TableModelEvent)
treeCollapsed(TreeExpansionEvent)
TreeExpansionListener none
treeExpanded(TreeExpansionEvent)
treeNodesChanged(TreeModelEvent)
treeNodesInserted(TreeModelEvent)
TreeModelListener none treeNodesRemoved(TreeModelEvent)
treeStructureChanged(TreeModelEvent)
TreeSelectionListener none valueChanged(TreeSelectionEvent)
TreeWillExpandListene treeWillCollapse(TreeExpansionEvent)
r none treeWillExpand(TreeExpansionEvent)
undoableEditHappened(UndoableEditEvent
UndoableEditListener none )
VetoableChangeListene
r none vetoableChange(PropertyChangeEvent)
windowGainedFocus(WindowEvent)
WindowFocusListener WindowAdapter
windowLostFocus(WindowEvent)
windowActivated(WindowEvent)
windowClosed(WindowEvent)
windowClosing(WindowEvent)
WindowListener WindowAdapter windowDeactivated(WindowEvent)
windowDeiconified(WindowEvent)
windowIconified(WindowEvent)
windowOpened(WindowEvent)
WindowStateListener WindowAdapter windowStateChanged(WindowEvent)
1036
First, make sure you registered the right kind of listener to detect the events. See whether another
kind of listener might detect the kind of events you need.
Make sure you registered the listener on the right object.
Did you implement the event handler correctly? For example, if you extended an adapter class, then
make sure you used the right method signature. Make sure each event-handling method is public
void, that the name spelled right and that the argument is of the right type.
If you still think that the component isn't generating the events it should, check the Java Developer
Connection to see whether this is a known bug.
Problem: My combo box isn't generating low-level events such as focus events.
Combo boxes are compound components — components implemented using multiple components.
For this reason, combo boxes don't fire the low-level events that simple components fire. For more
information, see Handling Events on a Combo Box.
Problem: The document for an editor pane (or text pane) isn't firing document events.
The document instance for an editor pane or text pane might change when loading text from a URL.
Thus, your listeners might be listening for events on an unused document. For example, if you load
an editor pane or text pane with HTML that was previously loaded with plain text, the document will
change to an HTMLDocument instance. If your program dynamically loads text into an editor pane or
text pane, make sure the code adjusts for possible changes to the document (re-register document
listeners on the new document, and so on).
If you don't see your problem in this list, see Solving Common Component Problems.
1037
Answer 1: You would register a ComponentListener on the component. The componentShown
method. This method is called when the window is first displayed or is deiconified.
Question 2: What listener would you implement to be notified when the user has finished editing a
text field by pressing Enter? What listener would you implement to be notified as each character is
typed into a text field? Note that you should not implement a general-purpose key listener, but a
listener specific to text.
Answer 2: To be notified when the user presses Enter, you would register an ActionListener on the
text field; the actionPerformed method is called when the user types Enter. Note that the Enter
character is not part of the resulting string. To be notified as each character is typed, you would
register a DocumentListener on the text field's Document. The insertUpdate method is then called
as each character is typed. Note that this is not the correct way to implement input validation. For
that behavior you should check out the Input Verification API section in How to Use the Focus
Subsystem.
Question 3: What listener would you implement to be notified when a spinner’s value has changed?
How would you get the spinner’s new value?
Answer 3: To be notified when the value has changed, you would register a ChangeListener on the
spinner. You would get the new value through the event's source in the stateChanged method. The
following code snippet shows how this could be done:
public void stateChanged(ChangeEvent e) {
JSpinner mySpinner = (JSpinner)(e.getSource());
SpinnerNumberModel model = (SpinnerNumberModel)(mySpinner.getModel());
Number currentValue = model.getNumber();
...
}
Question 4: The default behavior for the focus subsystem is to consume the focus traversal keys,
such as Tab and Shift Tab. Say you want to prevent this behavior in one of your application’s
components. How would you accomplish this?
Answer 4: You call setFocusTraversalKeysEnabled(false) on that particular component. Note
that you must then handle focus traversal manually. See How to Write a Key Listener and How to
Use the Focus Subsystem for more information.
Exercises
Exercise 1. Take the Beeper.java example and add a text field. Implement it so that when the user
has finishing entering data, the system beeps.
Answer 1: See Beeper1.java
Exercise 2. Take the Beeper.java example and add a selectable component that allows the user to
enter a number from 1 to 10. For example, you can use a combo box, a set of radio buttons, or a
spinner. Implement it so that when the user has selected the number, the system beeps that many
times.
Answer 2: See Beeper2.java
1038