Mouse Events and Interactive Graphics

Interactive graphics programs track the position of the mouse cursor in a panel and respond to events such as mouse button presses, cursor movement, and dragging (a combination of the two).  For example, to draw an oval, the user might press the mouse button at the ovalÕs upper left corner, drag the cursor down to ovalÕs lower right corner, and release the mouse button.

When a mouse event occurs in a panel, the corresponding handler method is triggered.  Default handler methods that do nothing are also defined in the GBPanel class but if the programmer overrides the relevant method in her subclass, the application can then respond to the event appropriately.  Here is a summary of the mouse event handler methods in BreezySwing.

 

Type of Event

GBPanel Method

What it does

Mouse press

mousePressed(x, y)

Triggered when the left mouse button is pressed.  x and y hold the mouse cursorÕs coordinates.

Mouse release

mouseReleased(x, y)

Triggered when the left mouse button is released.  x and y hold the mouse cursorÕs coordinates.

Mouse move

mouseMoved(x, y)

Triggered when the mouse is moved.  x and y hold the mouse cursorÕs coordinates.

Mouse drag

mouseDragged(x, y)

Triggered when the mouse is moved with left mouse button pressed.  x and y hold the mouse cursorÕs coordinates.

Mouse click

mouseClicked(x, y)

Triggered when the left mouse button is clicked.  x and y hold the mouse cursorÕs coordinates.

 

To illustrate the use of these methods in interactive graphics, we now present two programs that allow the user to draw geometric shapes in a panel.

The first program allows the user to draw filled oval shapes as described above (press the mouse, drag it down and to the right, and release it). The main window has a drawing area and a button that clears the drawings. The next screen shots show the program in action:

 

 

For this program and for the next one, you use code for a slightly different main window class, defined in DrawingDemo.java, than you did for previous graphics examples.  Here is the code for the main window:

 

import javax.swing.*;

import BreezySwing.*;

import java.awt.Color;

 

public class DrawingDemo extends GBFrame{

 

    DrawingPanel1 panel = new DrawingPanel1(Color.pink);

 

    public DrawingDemo(){

        addPanel(panel, 1,1,1,1);

        addButton("Clear", 2,1,1,1);

    }

 

    public void buttonClicked(JButton buttonObj){

        panel.clear();

    }

 

    public static void main (String[] args){

        JFrame frm = new DrawingDemo();

        frm.setSize (300, 300);

        frm.setVisible (true);

    }

 

}

 

Note that the panel object is now created before the constructor is defined, and that the actual class of the panel is explicitly named. This panel is then added to the window in the constructor. You do this so that the panel can be cleared in the buttonClicked method.

The panel class is defined in the file DrawingPanel1.java. As in an earlier example, the panel must maintain a list of things that are drawn. Since these things are ovals, you use the class java.awt.geom.Ellipse2D.Double (whew!) to represent them, and the interface java.awt.Shape as the element type of the list.

The methods mousePressed and mouseReleased collaborate to handle the user's mouse activity in the panel. The two methods share the instance variables mouseX and mouseY. These variables track the position of a mouse press. When the user presses the mouse, the mousePressed method sets these variables to the current mouse coordinates. This will be the upper left corner of the oval. The user then drags the mouse to the oval's lower right corner and releases it. At that point, the mouseReleased method verifies that the new mouse position is below and to the right of the old one, computes the width and height of the oval from the two pairs of coordinates, creates the oval, adds it to the list of shapes, and repaints the panel.

Here is the code for the new panel class:

import BreezySwing.*;

import java.awt.*;

import java.awt.geom.*;

 

public class DrawingPanel1 extends GBPanel{

 

    private java.util.List<Shape> shapes = new java.util.ArrayList<Shape>();

    private int mouseX = 0, mouseY = 0;  // Track the position of a mouse press

 

    public DrawingPanel1(Color color){

        setBackground(color);

    }

 

    public void paintComponent (Graphics g){

        // Clear the panel and redraw all the points

        super.paintComponent(g);

        g.setColor(Color.blue);

        for (Shape s : shapes)

            ((Graphics2D)g).fill(s);

    }

 

    public void mousePressed(int x, int y){

        // Remember the coordinates of the press event

        mouseX = x;

        mouseY = y;

    }

 

    public void mouseReleased(int x, int y){

        // Add the oval to the list of shapes and refresh the panel

        if (x <= mouseX || y <= mouseY)

            return;

        int width = x - mouseX;

        int height = y - mouseY;

        shapes.add(new Ellipse2D.Double(mouseX, mouseY, width, height));

        repaint();

    }

 

    public void clear(){

        // Clear the list of shapes and refresh the panel

        shapes = new java.util.ArrayList<Shape>();

        repaint();

    }

}

 

Note that the panel class includes a clear method, which creates a new list and repaints the panel. Also note that the paintComponent method draws a filled oval by calling the Graphics2D method fill with a shape as an argument. This method works with class that implements the Shape interface, so you will not have to change the code for paintComponent when you want to use other types of shapes (as in the next example).

The second program allows the user to do freehand drawing in a panel. Here is an example drawing, which shows the authors' artistic talent:

 

 

This program is structured very like the first one, but it draws tiny line segments in response to mouse drag events. A drag event occurs when the user presses and moves the mouse without releasing it. Therefore, when the user presses the mouse, the mousePressed method saves the mouse coordinates, as before. But when the user drags the mouse, the current mouse coordinates will be different from the saved ones, so the mouseDragged method creates a line segment from the two pairs of coordinates. It then adds the new line segment to the list of shapes and repaints the panel. Last but not least, to prepare for the next drag event, this method resets the saved coordinates to the new coordinates. The mouseReleased method is no longer needed.

Here is the code for the freehand drawing program, in the file DrawingPanel2.java:

import BreezySwing.*;

import java.awt.*;

import java.awt.geom.*;

 

public class DrawingPanel2 extends GBPanel{

 

    private java.util.List<Shape> shapes = new java.util.ArrayList<Shape>();

    private int mouseX = 0, mouseY = 0;  // Track the position of a mouse press

 

    public DrawingPanel2(Color color){

        setBackground(color);

    }

 

    public void paintComponent (Graphics g){

        // Clear the panel and redraw all the line segments

        super.paintComponent(g);

        g.setColor(Color.blue);

        for (Shape s : shapes)

            ((Graphics2D)g).fill(s);

    }

 

    public void mousePressed(int x, int y){

        // Remember the coordinates of the press event

        mouseX = x;

        mouseY = y;

    }

 

    public void mouseDragged(int x, int y){

        // Add a line segment to the list, remember the new mouse position, and refresh the panel

        shapes.add(new Line2D.Double(mouseX, mouseY, x, y));

        mouseX = x;

        mouseY = y;

        repaint();

    }

 

    public void clear(){

        // Clear the list of shapes and refresh the panel

        shapes = new java.util.ArrayList<Shape>();

        repaint();

    }

}

 

 

As you can see, the paintComponent and clear methods are exactly the same in both example programs. By now, you should be able to read the code and recognize the common design patterns employed. Think about how your would add menus to the main window to change the color and thickness of the drawing "pen," among other things.

 

Back to tutorial Next topic: Organizing widgets with panels