13.5 Mouse Events
Mouse events are handled in ways similar to those used with button events.
Mouse events, however, are slightly more complex because there are many
things that we can do with a mouse while the only thing that we can do
with a button is press it.
To use a mouse, we again register a class as a listener. In order to make
efficient use of system resources, there are two kinds of listener interfaces
associated with mouse events: MouseListener and MouseMotionListener.
Registration of a class as a listener takes a form similar to that used with
button events. Implementation of the MouseListener interface requires
the implementation of all of the following five methods.
- public void mousePressed (MouseEvent e)
This method is called when a mouse button is pressed within the
component to which we are listening.
- public void mouseReleased (MouseEvent e)
This is called when a mouse button is released within the component
to which we are listening.
- public void mouseClicked (MouseEvent e)
This is called when the mouse is clicked (a press followed quickly by
a release) within the component to which we are listening.
- public void mouseEntered (MouseEvent e)
This is called when the mouse cursor enters the bounds of the component
to which we are listening.
- public void mouseExited (MouseEvent e)
This is called when the mouse cursor exits the bounds of the component
to which we are listening.
Implementation of the MouseMotionListener interface requires only two
methods.
- public void mouseMoved (MouseEvent e)
This is called when a mouse is moved, without a button being pressed,
over the component to which we are listening.
- public void mouseDragged (MouseEvent e)
This is called when a mouse is moved, with a button held down,
over the component to which we are listening. If a mouse is dragged
over more than one component, the events produced by dragging the
mouse are delivered to the component where the dragging originated.
The MouseEvent object e that appears as a parameter of each of these
methods is supplied automatically by Java. It can be used to get a great
deal of useful information about the event. We will only be using two
instance methods in the MouseEvent class:
- public int getX ()
This method returns the horizontal coordinate of the mouse when
the event occurred.
- public int getY ()
This method returns the vertical coordinate of the mouse when the
event occurred.
In both cases, the coordinates are given relative to the component involved
in the event. Thus, clicking the mouse at the upper left hand corner of a
component will produce an event with coordinates (0, 0) no matter where
the component is located on the screen.
Other methods are available in the MouseEvent class to indicate which
mouse button was involved in the event, to give the identifier of the component
that was clicked, to indicate whether or not a double click had
occurred, and so on. These are all beyond the scope of this book.
To show how mouse events work in a program, let us create a very
simple drawing program that paints a small black circle at any point at
which we click the mouse within a window.
Example 1
The following program will draw a filled circular region of radius 10 pixels
at any point at which the mouse is clicked (within the window created by
the program).import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MouseCircles implements MouseListener
{
int x = -1;
int y;
static final int RADIUS = 10;
Drawing draw = new Drawing();
public MouseCircles()
{
JFrame frame = new JFrame("Mouse Droppings");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
draw.addMouseListener(this);
frame.add(draw);
frame.setSize(300,100);
frame.setVisible(true);
}
public void mouseClicked (MouseEvent e)
{
x = e.getX();
y = e.getY();
draw.repaint();
}
public void mousePressed (MouseEvent e)
{
}
public void mouseReleased (MouseEvent e)
{
}
public void mouseEntered (MouseEvent e)
{
}
public void mouseExited (MouseEvent e)
{
}
class Drawing extends JComponent
{
public void paint(Graphics g)
{
if (x != -1)
g.fillOval(x - RADIUS, y - RADIUS, 2 * RADIUS, 2 * RADIUS);
}
}
public static void main(String[] args)
{
new MouseCircles();
}
}
Here is a typical image produced by the program. Each click of the mouse
within the window produces a new circle centred at the point of the click.
|
|
There are a number of points that should be noted in this program.
- public class MouseCircles implements MouseListener
The implements clause promises that the CircleFrame class contains
all the methods of the MouseListener interface.
- int x;
int y;
These fields are the coordinates of the centres of the circular regions
that the program draws.
- draw.addMouseListener(this);
The draw object should be added to the list of
objects that act as listeners to mouse clicks.
- public void mouseClicked (MouseEvent e)
The mouseClicked method obtains the coordinates of the location
of any mouse click (within the current component’s area) from the
MouseEvent object e and then asks Java to schedule the component
for painting.
Note: to qualify as a click the mouse must not move
between pressing the mouse button and releasing it. For that reason,
especially if programming a game with many mouse clicks it may
be preferable to use mouseReleased instead of mouseClicked
- mousePressed, mouseReleased, mouseEntered, mouseExited
Although we do not want to take any action for mouse pressing,
releasing, and so on, we must include all of these methods in order
to implement the interface. To satisfy these requirements here, we
have supplied methods (sometimes called stub methods) whose bodies
contain no statements.
- public void paint (Graphics g)
The paint method simply draws a filled circular region with radius
given by RADIUS and centre at the most recent mouse click.
To save a lot of writing when dealing with listeners that have more
than one method, Java has a number of adapter classes that implement
listener interfaces in a trivial way, with stub methods. We can then create
a listener by extending the adapter class with our own handler class that
overrides the methods that we need with something useful and leaves the
other methods alone.
To illustrate, consider the mouse listener in Example 1. Java has a
class called MouseAdapter that contains trivial versions of all five methods
needed by a mouse listener. The form of each of the methods in
MouseAdapter is the same as four of our methods — a header with an
empty body. If we extend this class and provide a useful mouseClicked
method, we will have everything that we need.
As you might have expected, there are some small difficulties that we
must overcome to use this idea. We create a new class as our
handler and let that class extend MouseAdapter.
Creating a separate class, however, creates a new problem. We want
the mouseClicked method to be able to refer to the x and y fields of the
MouseCircles class and to be able to use repaint to activate the paint
method that is in the Drawing class. To overcome this problem,
we can create our handler class as an inner class of the MouseCircles class.
As we saw in Chapter 12, inner classes have exactly the properties that we
want here. The next example incorporates these ideas.
Example 2
The following code shows how we could change the program in Example 1
to avoid the need for writing stub methods in a class acting as a listener.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MouseCircles2
{
int x = -1;
int y;
static final int RADIUS = 10;
Drawing draw = new Drawing();
public MouseCircles2()
{
JFrame frame = new JFrame("Mouse Droppings");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
draw.addMouseListener(new ClickHandler());
frame.add(draw);
frame.setSize(300,100);
frame.setVisible(true);
}
class ClickHandler extends MouseAdapter
{
public void mouseClicked (MouseEvent e)
{
x = e.getX();
y = e.getY();
draw.repaint();
}
}
class Drawing extends JComponent
{
public void paint(Graphics g)
{
if (x != -1)
g.fillOval(x - RADIUS, y - RADIUS, 2 * RADIUS, 2 * RADIUS);
}
}
public static void main(String[] args)
{
new MouseCircles2();
}
}
Now, we no longer have the clause implements MouseListener in the
header of our main class. This is because the implementation of
MouseListener is done in the MouseAdapter class. The constructor of the
MouseCircles2 class has also been changed; it now calls the constructor of
the ClickHandler class to create a new ClickHandler object and then
puts that object on the mouse listener’s list of objects to be informed of
mouse events.
|
|
Exercise 13.5
- Explain the difference between the terms.
- mousePressed and mouseClicked
- MouseListener and MouseMotionListener
- MouseListener and MouseAdapter
- Although the designers of Java created adapter classes for MouseListener
and MouseMotionListener, they did not do so for ActionListener.
Do you think that this was an oversight, sheer laziness, or
something else? Justify your answer.
- Write a program that first allows the user to press the mouse at one
point on the screen, move the mouse (keeping the button pressed) to
another point, and then release the mouse. Once the user has done
this, the program should draw the line segment that connects the two
points.
- Write a program that allows the user to click on two points and
then draws the circle that has its centre at the first point and passes
through the second point.
|
|