Mouse clicks

Chapter: Interaction
...Section: Mouse clicks

In Lab 4 you wrote a program to perform some drawing based on mouse-clicks. Now we'll discuss some of the concepts behind it.

Whenever the user clicks the mouse inside the frame, a line is drawn from the last click-place to the current click place. The starting point for the first segment will be (0,0). The frame will have a quit button. To "listen" for mouse-clicks, we need an object that implements the MouseListener interface:

Interface MouseListener is defined as:

   public interface MouseListener extends EventListener {
     public abstract void mouseClicked (MouseEvent e);
     public abstract void mouseEntered (MouseEvent e);
     public abstract void mouseExited (MouseEvent e);
     public abstract void mousePressed (MouseEvent e);
     public abstract void mouseReleased (MouseEvent e);
   }

These five methods have to be overridden to successfully implement the interface.

However, we are only interested in mouse-click events. Here is the code:

import java.awt.*;
import java.awt.event.*;
class NewFrame extends Frame 
    implements ActionListener, MouseListener {
    
    // Constructor. 
    public NewFrame (int width, int height)
    {
	// Set the title and other frame parameters. 
	setTitle ("Button example");
	setResizable (true);
	setBackground (Color.cyan);
	setSize (width, height);
	
	// Create a quit button. 
	Button b = new Button ("Quit");
	b.setBackground (Color.red);
	b.setFont (new Font ("Serif", Font.PLAIN | Font.BOLD, 15));
	b.addActionListener (this);
	// setLayout (new BorderLayout()); 
	add (b, BorderLayout.SOUTH);
	
	// Add mouse-listening to the frame itself. 
	addMouseListener (this);
	
	// Show the frame. 
	setVisible (true);
    }
    
    // This method is required to implement the  
    // ActionListener interface. 
    public void actionPerformed (ActionEvent a)
    {
	// Button must have been pressed - so really quit. 
	System.exit (0);
    }
    
    int current_x=0, current_y=0;
    
    // These methods are required to implement  
    // the MouseListener interface. 
    public void mouseClicked (MouseEvent m)
    {
	System.out.println ("mouseClicked event: " + m.paramString());
	int x = m.getX();
	int y = m.getY();
	Graphics g = getGraphics();
	g.drawLine (current_x, current_y, x, y);
	current_x = x;
	current_y = y;
    }
    
    // We need to implement these methods, but 
    // don't actually have to do anything inside. 
    public void mouseEntered (MouseEvent m) {}
    public void mouseExited (MouseEvent m) {}
    public void mousePressed (MouseEvent m) {}
    public void mouseReleased (MouseEvent m) {}
    
} // End of class "NewFrame" 

public class TestAwt23 {
    
    public static void main (String[] argv)
    {
	NewFrame nf = new NewFrame (300, 200);
    }
    
}

You can see the result after a few random mouse clicks.

To handle mouse events (clicking, dragging, entering etc), a "mouse listener" needs to be passed to the widget that "sees" the events: The mouse events take place in the frame. Thus, we need to pass a "mouse listener" to the frame:

  add ( /* mouse listener */ );

In our example, the frame itself implements MouseListener. Therefore, we pass the frame itself:

    // Add mouse-listening to the frame itself. 
    this.addMouseListener (this);

The MouseListener interface was implemented by overriding all the abstract methods in the interface. The only one we were really interested in was mouseClicked(). For the others, we provided empty bodies:

  public void mouseEntered (MouseEvent m) {}
  public void mouseExited (MouseEvent m) {}
  public void mousePressed (MouseEvent m) {}
  public void mouseReleased (MouseEvent m) {}

Instead of implementing the MouseListener interface, it is possible to extend the MouseAdapter class. We did that in Lab 4. In this lab, however, our NewFrame is extending Frame and, because Java does not permit multiple inheritance, we cannot also extend MouseAdapter. We must await inner classes so that our frame does not need to be its own MouseListener.

The method MouseClicked is called whenever the mouse is clicked within the frame: The parameter MouseEvent carries information, e.g., the pixel coordinates of the place the mouse was clicked.

Observe that it is possible to draw in methods other than paint:

We drew in the method MouseClicked():

    Graphics g = this.getGraphics();
    g.drawLine (current_x, current_y, x, y);

To get the Graphics context, simply call the getGraphics() method of Component (inherited by NewFrame).


rhyspj@gwu.edu