Bruce Eckel’s Thinking in Java | Contents | Prev | Next |
boxes are significantly different from
Choice
boxes, and not just in appearance. While a
Choice
box drops down when you activate it, a List
occupies some fixed number of lines on a screen all the time and doesn’t
change. In addition, a
List
allows multiple selection: if you click on more than one item the original item
stays highlighted and you can select as many as you want. If you want to see
the items in a list, you simply call getSelectedItems( ),
which
produces an array of
String
of the items that have been selected. To remove an item from a group you have
to click it again.
problem with a
List
is that the default action is double clicking, not single clicking. A single
click adds or removes elements from the selected group and a double click calls
action( ).
One way around this is to re-educate your user, which is the assumption made in
the following program:
//: List1.java // Using lists with action() import java.awt.*; import java.applet.*; public class List1 extends Applet { String[] flavors = { "Chocolate", "Strawberry", "Vanilla Fudge Swirl", "Mint Chip", "Mocha Almond Fudge", "Rum Raisin", "Praline Cream", "Mud Pie" }; // Show 6 items, allow multiple selection: List lst = new List(6, true); TextArea t = new TextArea(flavors.length, 30); Button b = new Button("test"); int count = 0; public void init() { t.setEditable(false); for(int i = 0; i < 4; i++) lst.addItem(flavors[count++]); add(t); add(lst); add(b); } public boolean action (Event evt, Object arg) { if(evt.target.equals(lst)) { t.setText(""); String[] items = lst.getSelectedItems(); for(int i = 0; i < items.length; i++) t.appendText(items[i] + "n"); } else if(evt.target.equals(b)) { if(count < flavors.length) lst.addItem(flavors[count++], 0); } else return super.action(evt, arg); return true; } } ///:~
you press the button it adds items to the
top
of the list (because of the second argument 0 to
addItem( )).
Adding elements to a
List
is
more reasonable than the
Choice
box because users expect to scroll a list box (for one thing, it has a built-in
scroll bar) but they don’t expect to have to figure out how to get a
drop-down list to scroll, as in the previous example.
the only way for
action( )
to be called is through a double-click. If you need to monitor other activities
that the user is doing on your
List
(in particular, single clicks) you must take an alternative approach.
handleEvent( )
far we’ve been using
action( ),
but there’s another method that gets first crack at everything: handleEvent( ).
Any time an event happens, it happens “over” or “to” a
particular object. The
handleEvent( )
method for that object is automatically called and an Event
object is created and passed to
handleEvent( ).
The default
handleEvent( )
(which is defined in Component,
the base class for virtually all the “controls” in the AWT) will
call either action( ),
as we’ve been using, or other similar methods to indicate mouse activity,
keyboard activity, or to indicate that the focus has moved. We’ll look at
those later in this chapter.
if these other methods –
action( )
in particular – don’t satisfy your needs? In the case of
List,
for example, what if you want to catch single mouse clicks but
action( )
responds to only double clicks? The solution is to override
handleEvent( )
for your applet, which after all is derived from
Applet
and can therefore override any non-
final
methods. When you override
handleEvent( )
for the applet you’re getting all the applet events before they are
routed, so you cannot just assume “This has to do with my button so I can
assume it’s been pressed,” since that’s true only for
action( ).
Inside
handleEvent( )
it’s possible that the button has the focus and someone is typing to it.
Whether it makes sense or not, those are events that you can detect and act
upon in
handleEvent( ).
modify the
List
example so that it will react to single mouse clicks, the button detection will
be left in
action( )
but the code to handle the
List
will be moved into
handleEvent( )
as follows:
//: List2.java // Using lists with handleEvent() import java.awt.*; import java.applet.*; public class List2 extends Applet { String[] flavors = { "Chocolate", "Strawberry", "Vanilla Fudge Swirl", "Mint Chip", "Mocha Almond Fudge", "Rum Raisin", "Praline Cream", "Mud Pie" }; // Show 6 items, allow multiple selection: List lst = new List(6, true); TextArea t = new TextArea(flavors.length, 30); Button b = new Button("test"); int count = 0; public void init() { t.setEditable(false); for(int i = 0; i < 4; i++) lst.addItem(flavors[count++]); add(t); add(lst); add(b); } public boolean handleEvent(Event evt) { if(evt.id == Event.LIST_SELECT || evt.id == Event.LIST_DESELECT) { if(evt.target.equals(lst)) { t.setText(""); String[] items = lst.getSelectedItems(); for(int i = 0; i < items.length; i++) t.appendText(items[i] + "n"); } else return super.handleEvent(evt); } else return super.handleEvent(evt); return true; } public boolean action(Event evt, Object arg) { if(evt.target.equals(b)) { if(count < flavors.length) lst.addItem(flavors[count++], 0); } else return super.action(evt, arg); return true; } } ///:~
example is the same as before except for the addition of
handleEvent( ).
Inside, a check is made to see whether a list selection or deselection has
occurred. Now remember,
handleEvent( )
is
being overridden for the applet, so this occurrence could be anywhere on the
form and it could be happening to another list. Thus, you must also check to
see what the target is. (Although in this case there’s only one list on
the applet so we could have made the assumption that all list events must be
about that list. This is bad practice since it’s going to be a problem as
soon as another list is added.) If the list matches the one we’re
interested in, the same code as before will do the trick.
that the form for
handleEvent( )
is
similar to
action( ):
if
you deal with a particular event you
return
true,
but if you’re not interested in any of the other events via
handleEvent( )
you must
return
super.handleEvent(evt).
This is vital because if you don’t do this, none of the other
event-handling code will get called. For example, try commenting out the
return
super.handleEvent(evt)
in the code above. You’ll discover that
action( )
never gets called, certainly not what you want. For both
action( )
and
handleEvent( )
it’s important to follow the format above and always return the
base-class version of the method when you do not handle the event yourself (in
which case you should return
true).
(Fortunately, these kinds of bug-prone details are relegated to Java 1.0.
The new design in Java 1.1
that you will see later in the chapter eliminates these kinds of issues.)
Windows, a list box automatically allows multiple
selections if you hold down the shift key. This is nice because it allows the
user to choose a single or multiple selection rather than fixing it during
programming. You might think you’ll be clever and implement this yourself
by checking to see if the shift key is held down when a mouse click was made by
testing for
evt.shiftDown( ).
Alas, the design of the AWT stymies you – you’d have to be able to
know which item was clicked on if the shift key
wasn’t
pressed
so you could deselect all the rest and select only that one. However, you
cannot figure that out in Java 1.0.
(Java 1.1
sends all mouse, keyboard, and focus events to a
List,
so you’ll be able to accomplish this.)