Ashley Xu
Ashley Xu

Reputation: 25

How do I add MouseListeners to an individual panel in a grid of panels?

I'm trying to create a game of Reversi, and I'm in the beginning stages trying to figure out how to have a square respond to a click event. Here is my code so far.

To be clear, at the moment, I'm just trying to change the background color of a clicked panel in the grid. I'm still learning how ActionListeners work.

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.MouseListener;

public class Reversi {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        ReversiFrame frame = new ReversiFrame();
        frame.setSize(400,450);
        frame.setResizable(false);
        frame.setVisible(true);


    }  
}
/**
 * 
 * Class for the frame
 */
class ReversiFrame extends JFrame{

    /**
     * Constructor for ReversiFrame
     */
    public ReversiFrame(){

        super("Reversi");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JMenuBar bar = new JMenuBar();
        setJMenuBar(bar);

        JMenu gameMenu = new JMenu("Game");
        JMenu helpMenu = new JMenu("Help");

        bar.add(gameMenu);
        bar.add(helpMenu);

        final JMenuItem newGame = new JMenuItem("New Game");
        final JMenuItem exit = new JMenuItem("Exit");
        final JMenuItem help = new JMenuItem("Help");

        gameMenu.add(newGame);
        gameMenu.add(exit);
        helpMenu.add(help);

        /**
         * Exits program when exit menu item is clicked.
         */
        exit.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                dispose();
            }
        });

        ReversiPanel panel = new ReversiPanel();
        add(panel);


    }
}

class ReversiPanel extends JPanel{
    public static final int GRID_ROWS = 8;
    public static final int GRID_COLS = 8;
    public static final int HEIGHT = 50;
    public static final int WIDTH = 50;

    private GridPanel [][] panels = new GridPanel[GRID_ROWS][GRID_COLS];

    public ReversiPanel(){
        setLayout(new GridLayout(GRID_ROWS,GRID_COLS));
        setSize(HEIGHT, WIDTH);
        for(int row = 0; row < GRID_ROWS; row++){
            for(int col = 0; col < GRID_COLS; col++){
                panels[row][col] = (new GridPanel(row, col));
                setFocusable(true);
                panels[row][col].addMouseListener(new MouseAdapter(){
                    /*public void mouseClicked(MouseEvent e){
                        ((GridPanel)e.getSource()).getParent().setBackground(Color.red);
                        repaint();
                    }*/
                });
            }
        }
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        for(int row = 0; row < GRID_ROWS; row++){
            for(int col = 0; col < GRID_COLS; col++){
                panels[row][col].draw(g2);
            }
        }
    }
}

class GridPanel extends JPanel{
    public static final int HEIGHT = 50;
    public static final int WIDTH = 50;
    private boolean filled;
    private int numberGridsFilled = 0;
    private int x, y;


    public GridPanel(int row, int col){
        x = row * WIDTH;
        y = + col * HEIGHT;
        setSize(HEIGHT, WIDTH);
        filled = false;
        setBorder(BorderFactory.createLineBorder(Color.GRAY));
        setBackground(Color.red);

        addMouseListener(new MouseAdapter(){


            public void mouseClicked(MouseEvent e){
                setBackground(Color.RED);
                repaint();
            }
        });

    }



    public void draw(Graphics2D g2){
        g2.setPaint(Color.GRAY);
        Rectangle2D r = new Rectangle2D.Double(x, y, WIDTH, HEIGHT);
        g2.draw(r);
    }

    public void changeColor(){
        setBackground(Color.BLACK);
    }

    public void setColor() {
        setBackground(Color.BLACK);
    }
}

class Tile{
    private Color color;

    public Tile(Color color){

    }
}

Upvotes: 1

Views: 67

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347314

To start with, I wouldn't do panels[row][col].draw(g2); in your paintComponent, GridPanel extends from JPanel and JPanel is very capable of painting itself.

Start by getting rid the paintComponent method and add the GridPanels to the ReversiPanel...

public ReversiPanel() {
    setLayout(new GridLayout(GRID_ROWS, GRID_COLS));
    for (int row = 0; row < GRID_ROWS; row++) {
        for (int col = 0; col < GRID_COLS; col++) {
            panels[row][col] = (new GridPanel(row, col));
            add(panels[row][col]);
            setFocusable(true);
            panels[row][col].addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e){
                 ((GridPanel)e.getSource()).getParent().setBackground(Color.red);
                 repaint();
                 }
            });
        }
    }
}

When a component is added to a container (which is attached to a native peer), it becomes eligible for event notification

Now, in you GridPanel, replace the draw method with paintComponent and override the getPreferredSize to return the desired size of the component

class GridPanel extends JPanel {

    public static final int HEIGHT = 50;
    public static final int WIDTH = 50;
    private boolean filled;
    private int numberGridsFilled = 0;
    private int row, col;

    public GridPanel(int row, int col) {
        row = row;
        col = col;
        filled = false;
        setBorder(BorderFactory.createLineBorder(Color.GRAY));
        setBackground(Color.red);
    }

    public Dimension getPreferredSize() {
        return new Dimenions(WIDTH, HEIGHT);
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D)g.create();
        g2d.setPaint(Color.GRAY);
        Rectangle2D r = new Rectangle2D.Double(x, y, WIDTH, HEIGHT);
        g2d.draw(r);
        g2d.dispose();
    }

Upvotes: 4

Andrew Thompson
Andrew Thompson

Reputation: 168825

… trying to figure out how to have a square respond to a click event.

Make the square a (possibly undecorated) JButton instead of a JPanel. Give the button an icon, and/or text, then add an ActionListener.

A button with an action listener will respond to both mouse and keyboard events.

E.G. as seen in this answer to Add a complex image in the panel, with buttons around it in one customized user interface.

Upvotes: 3

Related Questions