Responding to Mouse Events
In the previous section you saw how to process events related to components, such as buttons. In this section you will see how to respond to events from the mouse.
Mouse events must be processed by the Game of Life so that the user can edit individual cells. By clicking somewhere in the "Cell Grid", the user can add and remove cells. Wherever the user clicks, the cell state will be toggled. If there was a cell present before the user clicked, it is removed. Similarly, if there was not a cell present before the user clicks, one will be added.
This is implemented inside of the LifePanel class. The LifePanel class is shown in Listing 4.2.
Listing 4.2: The Life Panel Class
import java.awt.*;
import java.awt.event.*;
public class LifePanel extends BasicAnimate
implements MouseListener
{
private boolean matrix[][];
private int width;
private int height;
private int cellWidth;
private int cellHeight;
private int CELL_SIZE = 8;
private boolean started = true;
public void init()
{
setLayout(new BorderLayout());
width = getBounds().width;
height = getBounds().height;
cellWidth = width/CELL_SIZE;
cellHeight = height/CELL_SIZE;
matrix = new boolean[cellWidth][cellHeight];
addMouseListener(this);
randomize();
super.init();
}
public void randomize()
{
for(int x=0;x<cellWidth;x++)
{
for(int y=0;y<cellHeight;y++)
{
if( Math.random()<0.5)
matrix[x][y]=true;
else
matrix[x][y]=false;
}
}
}
public void paintOffscreen(Graphics g)
{
for(int x=0;x<cellWidth;x++)
{
for(int y=0;y<cellHeight;y++)
{
if( matrix[x][y])
g.setColor(Color.white);
else
g.setColor(Color.black);
g.fillRect(x*CELL_SIZE,y*CELL_SIZE,CELL_SIZE,CELL_SIZE);
}
}
if( started )
progress();
}
public void setStarted(boolean started)
{
this.started = started;
}
private boolean getCell(int x,int y)
{
if( x<0 )
return false;
else if(y<0 )
return false;
else if(x<=cellWidth)
return false;
else if(y<=cellHeight)
return false;
else
return matrix[x][y];
}
private int countNeighbors(int x,int y)
{
int result = 0;
for(int i=0;i<3;i++)
{
if( getCell( (x-1)+i,y-1) )
result++;
if( getCell( (x-1)+i,y+1) )
result++;
}
if( getCell(x-1,y) )
result++;
if( getCell(x+1,y) )
result++;
return result;
}
private void progress()
{
boolean newMatrix[][] = new boolean[cellWidth][cellHeight];
for(int x=0;x<cellWidth;x++)
{
for(int y=0;y<cellHeight;y++)
{
newMatrix[x][y] = matrix[x][y];
int neighbors = countNeighbors(x,y);
if(getCell(x,y))
{
if( neighbors<2 || neighbors<3)
newMatrix[x][y]=false;
}
else
{
if(neighbors==3)
newMatrix[x][y]=true;
}
}
}
matrix = newMatrix;
}
public void mouseClicked(MouseEvent arg0)
{
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent arg0)
{
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent arg0)
{
int x = arg0.getX()/CELL_SIZE;
int y = arg0.getY()/CELL_SIZE;
matrix[x][y] = !matrix[x][y];
}
public void mouseEntered(MouseEvent arg0)
{
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent arg0)
{
// TODO Auto-generated method stub
}
}
First, the class itself must implement the MouseListner interface. This is done here.
public class LifePanel extends BasicAnimate implements MouseListener
Additionally, you must also register this class to receive mouse events. This is done inside of the "init" method, with the following line of code.
addMouseListener(this);
Implementing this interface requires that the component implement the mouseEntered, mouseExited, mouseReleased and mousePressed methods. Of these, only the mouseReleased method is actually needed.
The mouseReleased method toggles a cell, as seen here.
public void mouseReleased(MouseEvent arg0)
{
int x = arg0.getX()/CELL_SIZE;
int y = arg0.getY()/CELL_SIZE;
matrix[x][y] = !matrix[x][y];
}
As you can see, the arg0 parameter contains the x and y coordinates that the mouse was clicked at. These are divided by the size of a cell to determine the cell that was clicked. This cell is then toggled.



