Mouse Input

The keyboard is fundamentally just a board with a bunch of buttons on it, but the mouse is a more complicated device. Not only does it have buttons (depending on the mouse, it could have one, two, three, or more buttons), but it also has movement and possibly a scroll wheel. That said, you can receive three different types of mouse events:

  • Mouse button clicks
  • Mouse motion
  • Mouse wheel scrolls

Mouse buttons behave like keyboard buttons, but without the key repetition. Mouse motion is broken down into x and y screen coordinates. Finally, mouse wheel events tell how far the wheel was scrolled. Each mouse event type has its own listener: MouseListener, MouseMotionListener, and MouseWheelListener. Each listener takes a MouseEvent as a parameter. Like KeyListener, the MouseListener interface has methods for detecting mouse presses, releases, and clicks (pressing and then releasing). We'll ignore clicks in our games just as we ignore KeyTyped events and deal with just presses and releases. You can tell which button was pressed or released by calling the getButton() method of MouseEvent. Also, the MouseListener interface has methods to signal when the mouse has entered and exited the component. Because the component we use covers the entire screen, we can ignore these methods as well. For mouse movement, you can detect two types of motion with the MouseMotionListener interface: regular motion and drag motion. Drag motion events occur when the user moves the mouse while holding down a button. For either type of motion, you can get the current position of the mouse by calling the getX() and getY() methods of MouseEvent. The MouseWheelListener uses a subclass of MouseEvent called MouseWheelEvent. It has the method getWheelRotation() to inspect how much the mouse wheel was moved. Negative values mean scrolling up, and positive values mean scrolling down. Okay, that's enough about mouse input basics. Let's create a program to try it out. The MouseTest program in Listing 3.3 draws a "Hello World!" message at the location of the mouse. When you click, it changes to "trail mode" by drawing the last 10 mouse locations to make a "trail." Scrolling with the mouse wheel causes the text color to change. As before, press Escape to exit.

Listing 3.3 MouseTest.java
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;
import com.brackeen.javagamebook.graphics.*;
import com.brackeen.javagamebook.test.GameCore;
/**
 A simple mouse test. Draws a "Hello World!" message at
 the location of the cursor. Click to change to "trail mode"
 to draw several messages. Use the mouse wheel (if available)
 to change colors.
*/
public class MouseTest extends GameCore implements KeyListener,
 MouseMotionListener, MouseListener, MouseWheelListener
{
 public static void main(String[] args) {
 new MouseTest().run();
 }
 private static final int TRAIL_SIZE = 10;
 private static final Color[] COLORS = {
 Color.white, Color.black, Color.yellow, Color.magenta
 };
 private LinkedList trailList;
 private boolean trailMode;
 private int colorIndex;
 public void init() {
 super.init();
 trailList = new LinkedList();
 Window window = screen.getFullScreenWindow();
 window.addMouseListener(this);
 window.addMouseMotionListener(this);
 window.addMouseWheelListener(this);
 window.addKeyListener(this);
 }
 public synchronized void draw(Graphics2D g) {
 int count = trailList.size();
 if (count > 1 && !trailMode) {
 count = 1;
 }
 Window window = screen.getFullScreenWindow();
 // draw background
 g.setColor(window.getBackground());
 g.fillRect(0, 0, screen.getWidth(), screen.getHeight());
 // draw instructions
 g.setRenderingHint(
 RenderingHints.KEY_TEXT_ANTIALIASING,
 RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
 g.setColor(window.getForeground());
 g.drawString("MouseTest. Press Escape to exit.", 5,
 FONT_SIZE);
 // draw mouse trail
 for (int i=0; i<count; i++) {
 Point p = (Point)trailList.get(i);
 g.drawString("Hello World!", p.x, p.y);
 }
 }
 // from the MouseListener interface
 public void mousePressed(MouseEvent e) {
 trailMode = !trailMode;
 }
 // from the MouseListener interface
 public void mouseReleased(MouseEvent e) {
 // do nothing
 }
 // from the MouseListener interface
 public void mouseClicked(MouseEvent e) {
 // called after mouse is released - ignore it
 }
 // from the MouseListener interface
 public void mouseEntered(MouseEvent e) {
 mouseMoved(e);
 }
 // from the MouseListener interface
 public void mouseExited(MouseEvent e) {
 mouseMoved(e);
 }
 // from the MouseMotionListener interface
 public void mouseDragged(MouseEvent e) {
 mouseMoved(e);
 }
 // from the MouseMotionListener interface
 public synchronized void mouseMoved(MouseEvent e) {
 Point p = new Point(e.getX(), e.getY());
 trailList.addFirst(p);
 while (trailList.size() > TRAIL_SIZE) {
 trailList.removeLast();
 }
 }
 // from the MouseWheelListener interface
 public void mouseWheelMoved(MouseWheelEvent e) {
 colorIndex = (colorIndex + e.getWheelRotation()) %
 COLORS.length;
 if (colorIndex < 0) {
 colorIndex+=COLORS.length;
 }
 Window window = screen.getFullScreenWindow();
 window.setForeground(COLORS[colorIndex]);
 }
 // from the KeyListener interface
 public void keyPressed(KeyEvent e) {
 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
 // exit the program
 stop();
 }
 }
 // from the KeyListener interface
 public void keyReleased(KeyEvent e) {
 // do nothing
 }
 // from the KeyListener interface
 public void keyTyped(KeyEvent e) {
 // do nothing
 }
}


The code in MouseTest is pretty straightforward, and there really isn't any weird behavior to work around. Whenever the mouse is moved, a new Point object is added to trailList. The Point object contains an x and y value. At most, 10 Points exist in the list. If the trail mode is on, the draw() method simply draws "Hello World" at every Point in the list. Otherwise, "Hello World" is drawn only at the first Point. Clicking the mouse toggles trail mode on and off.



   
Comments