Session 21

More General Event Listeners

CS 2530
Intermediate Computing

Text Fields and Areas

Suppose that we would like to define a window that looks like the one below. The user is able to type text into each box independently of the other.

text field and area demo

Let's write a Java class called TextEntryFrame. With the AWT's built-in classes and behavior, this turns out to be almost too easy:

    import java.awt.Frame;
    import java.awt.TextField;
    import java.awt.TextArea;

    public class TextCheckFrame extends Frame
      public TextCheckFrame()
        setTitle( "Text Component Examples" );
        setSize ( 300, 250 );

        add( "North", new TextField() );
        add( "South", new TextArea () );

This solution comes with a new exercise built right into it:

Suppose that we want any text typed into the text field to appear in the text area, too.

What changes do we have to make?

"What do you mean by that?", you ask?

interacting field and listener 1 interacting field and listener 2

interacting field and listener 3 interacting field and listener 4

interacting field and listener 5

Now our solution needs a custom listener!

Handling Mouse Events

Our BallWorlds and our CannonGame only handle events that generated by the active components -- a button and a slider -- that we added to it.

More generally, though, we will want to trap and respond to a mouse action anywhere within the frame. We also need to interact with the event objects that are passed to our listeners.

Any listener that wishes to monitor mouse activity must implement the MouseListener interface:

     public interface MouseListener
       public void mouseClicked ( MouseEvent e );
       public void mouseEntered ( MouseEvent e );
       public void mouseExited  ( MouseEvent e );
       public void mousePressed ( MouseEvent e );
       public void mouseReleased( MouseEvent e );

As you should guess, the MouseListener interface is part of the java.awt.event package. It specifies what an object must do to be a mouse listener within the Java Event Model.

Consider this simple frame that displays the coordinates of every mouse press. It defines a MouseKeeper class that listens for mouse events. A MouseKeeper responds to only one: mousePressed(). This listener has to maintain state information, the coordinates of the last mouse press, that the frame accesses each time it paints itself.

Notice that we have to define empty methods for the other four responsibilities of mouse listeners, because the interface requires them! More on that soon.

A Little Exercise

Modify MouseListenerFrame so that it:

As we saw in our cannon game, an AWT Graphics object can draw a line for us:

    g.drawLine( xStart, yStart, xEnd, yEnd );

A Little Solution

Here's a possible solution, MouseClickDistanceFrame. Now we have to define an active mouseReleased() method, to record the coordinates of the release and tell the frame to repaint itself.

This time, I stored the points as IVs in the frame. Remember: the inner class has access to all the private stuff of its containing class, and the containing class has access to everything in the inner class.

An Alternative to Empty Methods

We often find ourselves writing classes like MouseListenerFrame and MouseClickDistanceFrame, in which we want to define only one or two of the required methods in the MouseListener interface. Do we really have to write empty methods for the rest?

Not really. We just have to be sure that our class has them all. We can do that using an AWT class named MouseAdapter. Here's how.

An instance of MouseAdapter implements all five methods of the MouseListener interface, with empty methods. If we write a subclass of MouseAdapter, we have to implement only the methods we care about.

That sounds just like a 3-prong-to-2-prong electrical adapter in the "real world".

Here's an alternative MouseClickDistanceFrame that defines its listener as a subclass of MouseAdapter. Because we need to define custom behavior only for mouse presses and mouse releases, we only have to write those two methods.

(Notice, too, the new import static... directives at the top of this program. Java 1.5 introduced "static imports", so that we don't have to use fully qulaified names for the Math.pow() and Math.sqrt() method.)

Wrap Up

Eugene Wallingford ..... ..... October 30, 2012