Alternatives to action

Bruce Eckel’s Thinking in Java Contents | Prev | Next

Component
method

When
it’s called

action
(Event evt, Object what)

When
the “typical” event occurs for this component (for example, when a
button is pushed or a drop-down list item is selected)

keyDown
(Event evt, int key)

A
key is pressed when this component has the focus. The second argument is the
key that was pressed and is redundantly copied from
evt.key.

keyUp(Event
evt, int key)

A
key is released when this component has the focus.

lostFocus(Event
evt, Object what)

The
focus has moved away from the target. Normally,
what
is redundantly copied from
evt.arg.

gotFocus(Event
evt, Object what)

The
focus has moved into the target.

mouseDown(Event
evt,


int x, int y)

A
mouse down has occurred over the component, at the coordinates
x,
y.

mouseUp(Event
evt, int x, int y)

A
mouse up has occurred over the component.

mouseMove(Event
evt, int x, int y)

The
mouse has moved while it’s over the component.

mouseDrag(Event
evt, int x, int y)

The
mouse is being dragged after a
mouseDown
occurred over the component. All drag events are reported to the component in
which the
mouseDown
occurred until there is a
mouseUp.

mouseEnter(Event
evt, int x, int y)

The
mouse wasn’t over the component before, but now it is.

mouseExit(Event
evt, int x, int y)

The
mouse used to be over the component, but now it isn’t.

You
can see that each method receives an
Event
object along with some information that you’ll typically need when
you’re handling that particular situation – with a mouse event, for
example, it’s likely that you’ll want to know the coordinates where
the mouse event occurred. It’s interesting to note that when
Component’s
handleEvent( )
calls any of these methods (the typical case), the extra arguments are always
redundant as they are contained within the
Event
object. In fact, if you look at the source code for
Component.handleEvent( )
you can see that it explicitly plucks the additional arguments out of the
Event
object. (This might be considered inefficient coding in some languages, but
remember that Java’s focus is on safety, not necessarily speed.)

To
prove to yourself that these events are in fact being called and as an
interesting experiment, it’s worth creating an applet that overrides each
of the methods above (except for
action( ),
which
is overridden in many other places in this chapter) and displays data about
each of the events as they happen.

//: AutoEvent.java
// Alternatives to action()
import java.awt.*;
import java.applet.*;
import java.util.*;
 
class MyButton extends Canvas {
  AutoEvent parent;
  Color color;
  String label;
  MyButton(AutoEvent parent,
           Color color, String label) {
    this.label = label;
    this.parent = parent;
    this.color = color;
  }
  public void paint(Graphics  g) {
    g.setColor(color);
    int rnd = 30;
    g.fillRoundRect(0, 0, size().width,
                    size().height, rnd, rnd);
    g.setColor(Color.black);
    g.drawRoundRect(0, 0, size().width,
                    size().height, rnd, rnd);
    FontMetrics fm = g.getFontMetrics();
    int width = fm.stringWidth(label);
    int height = fm.getHeight();
    int ascent = fm.getAscent();
    int leading = fm.getLeading();
    int horizMargin = (size().width - width)/2;
    int verMargin = (size().height - height)/2;
    g.setColor(Color.white);
    g.drawString(label, horizMargin,
                 verMargin + ascent + leading);
  }
  public boolean keyDown(Event evt, int key) {
    TextField t =
      (TextField)parent.h.get("keyDown");
    t.setText(evt.toString());
    return true;
  }
  public boolean keyUp(Event evt, int key) {
    TextField t =
      (TextField)parent.h.get("keyUp");
    t.setText(evt.toString());
    return true;
  }
  public boolean lostFocus(Event evt, Object w) {
    TextField t =
      (TextField)parent.h.get("lostFocus");
    t.setText(evt.toString());
    return true;
  }
  public boolean gotFocus(Event evt, Object w) {
    TextField t =
      (TextField)parent.h.get("gotFocus");
    t.setText(evt.toString());
    return true;
  }
  public boolean
  mouseDown(Event evt,int x,int y) {
    TextField t =
      (TextField)parent.h.get("mouseDown");
    t.setText(evt.toString());
    return true;
  }
  public boolean
  mouseDrag(Event evt,int x,int y) {
    TextField t =
      (TextField)parent.h.get("mouseDrag");
    t.setText(evt.toString());
    return true;
  }
  public boolean
  mouseEnter(Event evt,int x,int y) {
    TextField t =
      (TextField)parent.h.get("mouseEnter");
    t.setText(evt.toString());
    return true;
  }
  public boolean
  mouseExit(Event evt,int x,int y) {
    TextField t =
      (TextField)parent.h.get("mouseExit");
    t.setText(evt.toString());
    return true;
  }
  public boolean
  mouseMove(Event evt,int x,int y) {
    TextField t =
      (TextField)parent.h.get("mouseMove");
    t.setText(evt.toString());
    return true;
  }
  public boolean mouseUp(Event evt,int x,int y) {
    TextField t =
      (TextField)parent.h.get("mouseUp");
    t.setText(evt.toString());
    return true;
  }
}
 
public class AutoEvent extends Applet {
  Hashtable h = new Hashtable();
  String[] event = {
    "keyDown", "keyUp", "lostFocus",
    "gotFocus", "mouseDown", "mouseUp",
    "mouseMove", "mouseDrag", "mouseEnter",
    "mouseExit"
  };
  MyButton
    b1 = new MyButton(this, Color.blue, "test1"),
    b2 = new MyButton(this, Color.red, "test2");
  public void init() {
    setLayout(new GridLayout(event.length+1,2));
    for(int i = 0; i < event.length; i++) {
      TextField t = new TextField();
      t.setEditable(false);
      add(new Label(event[i], Label.CENTER));
      add(t);
      h.put(event[i], t);
    }
    add(b1);
    add(b2);
  }
} ///:~ 

You
can see the constructor uses the technique of using the same name for the
argument as what it’s assigned to, and differentiating between the two
using
this:

this.label
= label;

The
paint( )
method starts out simple: it fills a “round rectangle” with the
button’s color, and then draws a black line around it. Notice the use of
size( )
to determine the width and height of the component (in pixels, of course).
After this,
paint( )
seems
quite complicated because there’s a lot of calculation going on to figure
out how to center the button’s label inside the button using the
“font metrics.” You can get a pretty good idea of what’s
going on by looking at the method call, and it turns out that this is pretty
stock code, so you can just cut and paste it when you want to center a label
inside any component.

The
place where you look up the strings is in the
keyDown( ),
keyUp( ),
etc. methods back in
MyButton.
Each of these methods uses the
parent
handle to reach back to the parent window. Since that parent is an
AutoEvent
it contains the
Hashtable
h
,
and the
get( )
method, when provided with the appropriate
String,
will produce a handle to an
Object
that we happen to know is a
TextField
– so it is cast to that. Then the
Event
object is converted to its
String
representation, which is displayed in the
TextField.

More by Author

Must Read