1

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

    }
}
Ashley Xu
  • 25
  • 6
  • This question is a bit too broad. In it's current state, it's essentially "write this code for me". You should narrow your question down to something more specific. (Ideally, something that can be demonstrated without needing the entire body of your code) – Retsam Apr 13 '15 at 05:16
  • Yeah, it's kind of hard to articulate what I want to ask, because I think I could look it up much easier if I knew what to say. Basically the question is, "how do I refer to the panel itself on the event click to change the background?" Based on someone else's answer, it seems to be e.getSource(), but correct me if something else would help. – Ashley Xu Apr 13 '15 at 05:20

2 Answers2

4

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();
    }
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you so much for your help! That explained exactly what I wanted to know. Sometimes it's hard to ask questions correctly as a novice. Thanks again! I wish I could upvote you, but I just created an account. =( – Ashley Xu Apr 13 '15 at 05:16
  • Glad it could help. Also, you could add the `MouseListener` directly within `GridPanel` instead, but that comes down to your own needs – MadProgrammer Apr 13 '15 at 05:19
  • Yeah, I tried that as well, but I couldn't figure out how to refer to the specific object of the GridPanel to change the background. If that makes sense? I tried to use this, but seemed to fail miserably. – Ashley Xu Apr 13 '15 at 05:22
  • `MouseEvent#getSource`? But if the `MouseListener` is controlled by `GridPanel` (as inner or anonymous class), then you can reference the `GridPanel` directly with `GridPanel.this` – MadProgrammer Apr 13 '15 at 05:27
3

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

Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • I would prefer to add the events to the panels, but if that's not possible, I will certainly try out your idea. Thanks for the advice! – Ashley Xu Apr 13 '15 at 05:15