Alternatives to action | CodeGuru

Alternatives to action

Bruce Eckel’s Thinking in Java Contents | Prev | Next As noted previously, action( ) isn’t the only method that’s automatically called by handleEvent( ) once it sorts everything out for you. There are three other sets of methods that are called, and if you want to capture certain types of events (keyboard, mouse, and focus events) […]

Written By
CodeGuru Staff
CodeGuru Staff
Mar 1, 2001
5 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

As


noted previously,


action( )

isn’t the only method that’s automatically called by

handleEvent( )
once it sorts everything out for you. There are three other sets of methods
that are called, and if you want to capture certain types of events (keyboard,
mouse, and focus events) all you have to do is override the provided method.
These methods are defined in the base class
Component,
so they’re available in virtually all the controls that you might place
on a form. However, you should be aware that this approach is deprecated in
Java 1.1
,
so although you might see legacy code using this technique you should use the
Java 1.1 approaches (described later in this chapter) instead.
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.

This


example also shows you how to make your own button object because that’s


what is used as the target of all the events of interest. You might first


(naturally) assume that to make a new button, you’d inherit from

Button.
But this doesn’t work. Instead, you inherit from
Canvas
(a much more generic component) and paint your button on that canvas by
overriding the
paint( )
method. As you’ll see, it’s really too bad that overriding
Button
doesn’t work, since there’s a bit of code involved to paint the
button. (If you don’t believe me, try exchanging
Button
for
Canvas
in this example, and remember to call the base-class constructor
super(label).
You’ll see that the button doesn’t get painted and the events
don’t get handled.)

The


myButton

class is specific: it works only with an


AutoEvent

“parent window” (not a base class, but the window in which this


button is created and lives). With this knowledge,


myButton

can reach into the parent window and manipulate its text fields, which is


what’s necessary to be able to write the status information into the


fields of the parent. Of course this is a much more limited solution, since


myButton

can be used only in conjunction with


AutoEvent

.


This kind of code is sometimes called “highly coupled.” However, to


make


myButton

more generic requires a lot more effort that isn’t warranted for this


example (and possibly for many of the applets that you will write). Again, keep


in mind that the following code uses APIs that are deprecated in Java 1.1

.
//: 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.

You


can’t understand exactly how the


keyDown( )

,


keyUp( ),

etc. methods work until you look down at the


AutoEvent

class. This contains a

Hashtable
to hold the strings representing the type of event and the
TextField
where information about that event is held. Of course, these could have been
created statically rather than putting them in a
Hashtable,
but I think you’ll agree that it’s a lot easier to use and change.
In particular, if you need to add or remove a new type of event in
AutoEvent,
you simply add or remove a string in the
event
array – everything else happens automatically.

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

.

It


turns out this example is rather fun to play with since you can really see


what’s going on with the events in your program.


Contents

|

Prev

|

Next
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.