| 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 . How do I handle action events in the JDK 1.1?
|
Ans :
Use the addActionListener
method to register an ActionListener
object with the event source; the listener's actionPerformed
method will be invoked when an action event occurs.
An
action event is the way some AWT components notify your program
that they have been acted on and now have new information to
report. The JDK 1.1 generates action events in the cases shown in
Table
Table:
Action Events—JDK 1.1
| Component |
Generates
JDK 1.1 action event for ___ |
Button |
mouse
click |
MenuItem |
mouse
click |
List |
double
mouse click |
| return key
press |
TextField |
return key
press |
Note that this list
differs from the JDK 1.0.2 AWT by omitting Checkbox
and Choice. These two classes now belong to a
separate category of ItemSelectable objects—that
is, objects from classes that implement the ItemSelectable
interface. The ItemSelectable interface is intended
to cover any class that has the semantics of a selection from a
specific, finite set of choices. In addition to Checkbox
and Choice, the List class implements
the ItemSelectable interface as well.
To catch and handle an action event,
you need to attach an ActionListener object to the
source of the event. The listener's actionPerformed
method is invoked for each action event on the source component.
The following code fragment shows how to catch action events from
three different components with the same listener:
/* using JDK 1.1: */
class Example {
/** An inner class that reports action events received. */
class ActionReporter implements ActionListener {
public void actionPerformed(ActionEvent e) {
++actionCount;
actionEventLog.append("Action event #" + actionCount
+ ", e = " + e + "\n");
}
}
ActionListener reporter = new ActionReporter();
TextArea actionEventLog = new TextArea();
int actionCount;
public void init() {
List animalList = new List(3, false);
Button pushButton = new Button("Push Me");
TextField text = new TextField(
"Type in me (and hit return).");
/* Initialize event handlers. */
animalList.addActionListener(reporter);
pushButton.addActionListener(reporter);
text.addActionListener(reporter);
}
}
This
sample code uses an inner class, ActionReporter, to
define the ActionListener. The inner class simplifies
the event handling code by providing direct access to the Example
class's instance variables, actionCount and ActionEventLog.
Using a standard (non-inner) class would be much clumsier: you
would have to set up extra methods or constructors to pass the
necessary information between the Example instance
and the ActionReporter instance.
|
|
Q . How do I catch menu item events in the 1.1 AWT event model?
|
Ans :
Menu items
emit an ActionEvent
when clicked, so you can catch menu item events the same way as
other action events, with an ActionListener
object.
In
the JDK 1.1 AWT event model, clicking on a menu item sends an
action event to any ActionListener objects that have
registered themselves with that menu item. There are two main
strategies for how to assign listeners to the numerous menu items
in a typical menu system: a unique listener for each menu item
versus one large listener for all menu items. The code excerpt
below illustrates the listener-per-item approach:
/* using JDK 1.1: */
class Example {
/** Inner class for use as the "File Open" listener. */
class MenuFileOpen implements ActionListener {
public void actionPerformed(ActionEvent e) {
openFile(e.getActionCommand());
}
}
/** Inner class for use as the "File Save" listener. */
class MenuFileSave implements ActionListener {
public void actionPerformed(ActionEvent e) {
saveFile(e.getActionCommand());
}
}
public void init() {
MenuItem openItem = new MenuItem("Open...");
openItem.addActionListener(new MenuFileOpen());
MenuItem saveItem = new MenuItem("Save");
saveItem.addActionListener(new MenuFileSave());
// ... assemble the menu system and show the main frame
}
// ... define openFile and saveFile
}
The
one-large-listener approach, on the other hand, requires that you
explicitly propagate that listener to all the menu items in your
menu hierarchy. The following method, for example, recursively
walks down the menu hierarchy in order to attach an ActionListener
object to each menu item:
/* using JDK 1.1: */
static void addMenuListenerRecursively(MenuItem mi,
ActionListener listener) {
mi.addActionListener(listener);
if (mi instanceof Menu) {
Menu m = (Menu) mi;
for (int i = 0; i < m.getItemCount(); ++i) {
addMenuListenerRecursively(m.getItem(i), listener);
}
}
}
After
you've built your entire menu structure, including the menu bar,
you can invoke this method on each of the menus contained in menu
bar:
for (int i = 0; i < myMenuBar.getMenuCount(); ++i) {
ddMenuListenerRecursively(myMenuBar.getMenu(i), tracker);
|
|
Q . In the JDK 1.1 AWT event model, how is my program notified when a list item is selected or deselected?
|
Ans :
When an
item in a list is selected or deselected, the AWT invokes itemStateChanged
on any ItemListener registered with
that list; you can then query the ItemEvent
for whether the state change is a select (ItemEvent.SELECTED)
or a deselect (ItemEvent.DESELECTED).
The
JDK 1.1 AWT event model makes a strong division between low-level
events and semantic events. Low-level events represent raw input
actions or window-system state changes, whereas semantic events
represent meaningful happenings brought about by lower-level
actions. Semantic events are defined in terms of a semantic model
and can be generated by any user-interface element that supports
that model. Thus, the semantic event generated by a List
is not a ListEvent (no such event class exists) but
an ItemEvent. An ItemEvent can in
principle be generated by any class that supports a model of an
item collection within which individual items are selected or
deselected. If your class fits such a model, you are encouraged to
use the ItemSelectable interface and ItemEvent
class for your class's event behavior.
You catch item events from a List
instance by registering one or more ItemListener
objects with that instance. The ItemListener
interface contains a single method:
/* in Listener.java (JDK 1.1): */
public interface ItemListener extends EventListener {
public void itemStateChanged(ItemEvent e);
}
Although the same
event method is delivered whether the user selected or deselected
an item, you can distinguish between the two by querying the ItemEvent
object with its getStateChange method. A select event
yields the int value ItemEvent.SELECTED,
and a deselect event yields ItemEvent.DESELECTED. For
example:
/* using JDK 1.1: */
if (e.getStateChange() == ItemEvent.SELECTED) {
// ... handle select event
} else {
// ... handle deselect event
}
List
objects also produce action events, when the user either double
clicks an item or presses the return key while an item has
keyboard focus. You can catch these action events with an ActionListener
object, the same as for other action events from other sources.
|
|
Q . How do I control scrolling in the 1.1 AWT?
|
Ans :
The JDK
1.0.2 forces you to handle scrolling on your own, but the JDK 1.1
\provides the ScrollPane
class as a ready-made container to handle scrolling automatically.
The ScrollPane
class, new in the JDK 1.1, provides a ready-made scrolling
container. ScrollPane is a subclass of Container
that takes a single component as its child and manages horizontal
and vertical scrolling for the child component. For basic
scrolling behavior, using a ScrollPane can be as
simple as creating a ScrollPane instance and adding
your component to it. All the scrolling behavior is managed
automatically by the scroll pane. The following simple class shows
a scroll pane holding a panel, which contains 400 buttons in a
20-by-20 grid:
/* using JDK 1.1: */
class Example {
/** Initializes the app, builds the interface. */
public void init() {
Frame mainFrame = new Frame("ScrollPane11Example");
ScrollPane scrollPane = new ScrollPane();
Panel buttonPanel = new Panel();
buttonPanel.setLayout(new GridLayout(0, 20));
for (int i = 0; i < 400; ++i) {
buttonPanel.add(new Button("B" + i));
}
scrollPane.add(buttonPanel);
mainFrame.add(scrollPane, "Center");
mainFrame.pack();
mainFrame.show();
}
/** Runs the class as a standalone application. */
public static void main(String[] args) {
Example example = new Example();
example.init();
}
}
As this example shows,
if you want a collection of components to be scrollable as a
group, place them in a panel and then place that Panel inside the
scroll pane.
The ScrollPane class's
default behavior is reasonable for many uses, but the class also
provides programmatic control over the following aspects:
- scrollbar
policy: can be set in the constructor; its possible values are
SCROLLBARS_AS_NEEDED, SCROLLBARS_ALWAYS,
and SCROLLBARS_NEVER
- scroll position:
can be set programmatically via
setScrollPosition(int,
int) and can be queried with getScrollPosition()
- scrollbars:
horizontal and vertical scrollbars of the ScrollPane instance
can be inspected individually with
getHAdjustable()
and getVAdjustable()
You can also take
internal measurements of the scroll pane with the following
methods:
public Dimension getViewportSize()
public int getHScrollbarHeight()
public int getVScrollbarWidth()
|
|
|
|