Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use MouseListener to find a specific cell in a grid

I'm trying to create a Java game with a 10 x 10 grid made up of cells. The Grid looks liks this:

public class Grid extends JPanel implements MouseListener {
    public static final int GRID_SIZE = 10;

    public Grid() {
        setPreferredSize(new Dimension(300, 300));
        setLayout(new GridLayout(GRID_SIZE, GRID_SIZE));

        for (int x = 0; x < GRID_SIZE; x++)
            for (int y = 0; y < GRID_SIZE; y++)
                add(new Cell(x, y));
        addMouseListener(this);
    }

// All Mouse Listener methods are in here.

The Cell class looks like this:

public class Cell extends JPanel {

    public static final int CELL_SIZE = 1;
    private int xPos;
    private int yPos;

    public Cell (int x, int y) {
        xPos = x;
        yPos = y;
        setOpaque(true);
        setBorder(BorderFactory.createBevelBorder(CELL_SIZE));
        setBackground(new Color(105, 120, 105));
        setPreferredSize(new Dimension(CELL_SIZE, CELL_SIZE));
    }

    // Getter methods for x and y.

My issue is that I am now trying to implement the MouseListeners in the Grid class. What I have realised is that whilst I can return the X and Y coordinates of the Grid, I can't seem to manipulate the cells themselves. I am assuming this is because when I created them in Grid, I am creating 100 random Cells with no identifiers and so I have no way to directly access them.

Could anybody give me advice on this? Do I need to overhaul my code and the way I am creating the cells? Am I being terribly stupid and missing an obvious way of accessing them? Thanks

like image 744
Andrew Martin Avatar asked Apr 24 '13 13:04

Andrew Martin


3 Answers

You could use an adapter pattern, as shown below. That way, you can add the listener to each grid cell individually, but still handle the events from Grid.

Note that Grid no longer implements MouseListener, this is handled by the cells now.

public class Grid extends JPanel {
    public static final int GRID_SIZE = 10;

    public Grid() {
        setPreferredSize(new Dimension(300, 300));
        setLayout(new GridLayout(GRID_SIZE, GRID_SIZE));

        for (int x = 0; x < GRID_SIZE; x++) {
            for (int y = 0; y < GRID_SIZE; y++) {
                final Cell cell = new Cell(x, y);
                add(cell);
                cell.addMouseListener(new MouseListener() {
                    public void mouseClicked(MouseEvent e) {
                        click(e, cell);
                    }
                    // other mouse listener functions
                });
            }
        }        
    }

    public void click(MouseEvent e, Cell cell) {
        // handle the event, for instance
        cell.setBackground(Color.blue);
    }

    // handlers for the other mouse events
}

A subclass could override this as:

public class EnemyGrid extends Grid {
    public void click(MouseEvent e, Cell cell) {
        cell.setBackground(Color.red);
    }
}
like image 156
Vincent van der Weele Avatar answered Oct 19 '22 12:10

Vincent van der Weele


  • use put/getClientProperty

  • you can to multiple this method, with other additional parameters

  • example about How to determine clicked JButton in a grid, the same logics for JPanel and Mouse(Xxx)Listener

  • override getPreferredSize(new Dimension(x, y)) for JPanel instead of setPreferredSize(new Dimension(CELL_SIZE, CELL_SIZE));

like image 2
mKorbel Avatar answered Oct 19 '22 10:10

mKorbel


The most obvious way would be to move your MouseListener on the Cell class itself.

Second option I can think of is to use java.awt.Container.getComponentAt(int, int).

like image 1
Guillaume Polet Avatar answered Oct 19 '22 10:10

Guillaume Polet