Listeners

advertisement
Java 211 – Lecture X
Events and Listeners
Yosef Mendelsohn
Events
At this point in your programming, you have learned how to get input from the user from
the keyboard. For example, you may want to read in a string of text, or an integer value,
or some other type of textual data. However, input to your program can come in many
forms. For example, many situations in computers receive input from other sources such
as the mouse. Clicking on the left-mouse button is one of many possible “events” in
which your program may be interested.
For example, you have all seen dialog boxes in which you have to click on ‘OK’ or
‘CANCEL’. These dialog boxes typically require input from the mouse to which the
program will then respond accordingly.
In Java, events can be generated all kinds of ways:
- clicking on a mouse button
- pressing the up-arrow key on your keyboard
- clicking on the ‘OK’ button in a dialog box
- clicking on the down-arrow button at the bottom of a slider
The Java standard class library contains many classes that represent events in which the
programmer may be interested.
Methods in the MouseListener interface
Following is a list of events that can be generated by a mouse. All of these events are
present as (abstract) methods inside an interface called ‘MouseListener’.
- mousePressed
- mouseReleased
- mouseClicked
- mouseEntered
- mouseExited
For example, in a properly implemented program, a single-click on the left mouse button
will cause the methods mousePressed(), mouseReleased(), and mouseClicked() to be
executed.
You can get a program to respond to one or more of these methods by creating a class
that implements the MouseListener interface. Naturally, implementing the
MouseListener interface means that we must implement all of the above methods.
However, we do not have to give all of the methods valid bodies; some of them may be
empty methods. Depending on the situation, we will implement one or more of the
methods with code to respond appropriately.
MouseMotionListener interface
Two other events you may want to have your program respond to are: mouseMoved, and
mouseDragged. These abstract methods are in the MouseMotionListener inteface. These
events (methods) are continually called as the mouse is moved and/or dragged.
Listeners
By implementing some of the various methods discussed above, you are writing code that
will get executed when some event in your program takes place For example, if the user
clicks on a certain button in an applet, the mousePressed, mouseReleased, and
mouseClicked events in the appropriate class will be invoked. However, a question
remains: How does the program know which class to invoke? For example, you may
have fifteen different classes all of which implement the MouseListener interface
differently. Which class’ methods should be invoked in response to clicking on the
button in your applet?
The answer, is to make a “connection” between the object you want “responded” to (e.g.
the button in your applet) and another object called a listener. When an event occurs, the
button (i.e. the listener object) that generated the event will notify the listener object. The
listener object will then automagically invoke all the appropriate methods of that listener.
The Java standard class library contains a number of listener interfaces. Each interface is
a collection of methods grouped by category. For example, the MouseListener interface
or the MouseMotionListener interface. Another commonly used interface is the
KeyListener which listens and responds to key press events on the keyboard.
MouseEvent class
When an event occurs (e.g. the mouse button is released), the appropriate event (method)
is automatically called. In this, case, the mouseReleased method. Examination of the
signature of the mouseReleased method shows that the method takes one parameter of
type MouseEvent. When the mouseReleased method is called, the program automatically
passes along a parameter of type MouseEvent. This MouseEvent object contains
(encapsulates) all kinds of information about the event that occurred. For example, the
MouseEvent object contains, among other information, the x and y coordinates of the
location on the screen where the mouse was clicked.
Some methods of the MouseEvent class include:
- getX (returns an int)
- getY (returns an int)
- getPoint (returns a Point object)
Connecting the event generator to a listener class
All components that can generate events such as buttons, drop-down menu boxes, or
applets, have methods we can invoke that will “connect” the item that generates the event
(e.g. an applet) with the appropriate listener class that is supposed to respond to it.
For example, since applets are sometimes meant to respond to mouse clicks (just like
buttons are), the applet class has a method called ‘addMouseListener()’ that allows you to
add a MouseListener object to the applet.
FYI: The addMouseListener() method is defined in class ‘Component’, not in class
‘Applet’. This makes sense since you may want to invoke this method for many different
types of objects, not just applets. That is, every object that is a component object, can
invoke the addMouseListener() method.
Question: Are applets components?
Generating the event
Note: Even though it is the mouse that actually does the clicking, the event is actually
considered as having been generated by the object that was clicked on. So in the above
example, the applet is said to have “generated the event”.
See MouseClickApplet.java
To summarize:
1. Begin with an object that can generate an event (e.g. an applet or a button)
2. Decide which kinds of events you would like your object to generate (e.g. mouse
clicks, keyboard presses, etc.)
3. Create a listener class for the event (or events) that you want responded to. For
example, if you wish an applet to generate events when the mouse is clicked, you
would need to create a MouseListener or MouseMotionListener class. You can
create such a class by implementing the MouseListener (or
MouseMotionListener) interface.
4. “Add” the listener to the class that generates the events. For example, in the case
of an applet, you would call the method ‘addMouseListener’ from inside the
applet. The addMouseListener method connects the event-generating class (the
applet) with the listener class. The addMouseListener method takes one argument
of type MouseListener.
So you must have at least one class around that has implemented the
MouseListener interface. You can then instantiate that class and pass it as
an argument to the addMouseListener interface.
See Dots.java and DotsMouseListener.java
Don’t Forget: When a listener class is notified that an event has occurred, the listener
class calls all of the appropriate methods based on the event that occurred (e.g.
mousePressed). Each method of the listener takes one argument. The argument contains
all kinds of information about the event that took place. For example, if a key on the
keyboard was pressed, the event object encapsulates information about what key was
pressed. If a mouseListener class is involved, the event encapsulates information such as
the x and y coordinates of the location where the mouse was clicked.
Making the event-generator a listener
To make any class a listener class is easy. You simply put the ‘implements’ clause after
the class header, and then implement all of the methods in that interface. That is, any
class that implements one of the interface listeners is automatically a listener class. For
example, to make an applet called DumbApplet a MouseListener, we could do the
following:
class DumbApplet extends Applet implements MouseListener {
Notice how DumbApplet is now both an applet and a MouseListener. Now you don’t
have to worry about creating a separate class as a listener. You need only implement the
methods from the MouseListener class inside the applet, and you are home free. This
saves you from having to create another class, import it, and instantiate it inside the
applet. Instead, you can “add” the listener class to your applet (step 4 above) by using
the following line:
addMouseListener(this);
//the calling object (i.e. the applet)
// also serves as a mouseListener object
This calls the addMouseListener method of the Applet class (or, more accurately, of the
Container class). Don’t forget that addMouseListener requires a MouseListener object as
its argument. However, since the applet is also a MouseListener, you can pass ‘this’ as
the argument and, voila, you have connected your event-generator to a listener.
Now take a look at RubberLines.java. Notice how in this program (just like the
MouseClickApplet we examined earlier), the applet itself is implemented as a listener.
Again, this saves us from some of the complications of the Dots programs since we don’t
have to create separate classes, instantiate them, etc.
It must be noted that while having the event-generator do double-duty as a listener is
convenient, it is also in conflict with the idea of modularity. Typically, we should design
our classes to carry out only the objectives necessary to the proper use and functionality
of that class. Implementing a complicated interface within an applet is not always a good
idea. It is always better to distribute responsabilities among various classes.
There is one compromise: If a listener is designed to work only with one specific
component (e.g. a specific applet), you can write a separate listener class, but make it a
nested class. See Direction.java. In this case, you are accomplishing the objective of
properly delegating tasks to specific classes, while at the same time, reducing the
complexities involved in communication between the event-generator and the listener
class.
In Direction.java we see some new things:
- using Images
- using the KeyListener interface (look up in API)
- using sounds (look up AudioClip in the API)
- nested classes
At this point, take another look at the Dots programs discussed earlier. Notice the extra
work involved in separating the classes out:
- two separate classes in separate files
- the listener class must be instantiated in the applet
- a reference to the applet must be maintained inside the listener class
private Dots applet;
As your programs become more involved, you will have to follow this method, but for
simpler applications, you can use nested classes.
Download