How to use MouseListener to find a specific cell i

2020-04-07 04:53发布

问题:

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

回答1:

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);
    }
}


回答2:

  • 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));



回答3:

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).