views:

113

answers:

3

I'm working on a GUI for a chess game and I was wondering if there's any way to check for a series of clicks, for example: user clicks on jPanel THEN user clicks on another jPanel that exists in valid move array. I know I could use a variable to store some kind of state like "isSquareClicked = true" or something but I'd rather not unless that's the only way...

+1  A: 

As I know, there is no such things in Java.

But:

1) As I understand, You use field of 8x8 JPanels to create field for game? IMHO this is bad way. If I were you, I would use one Panel for creating field - by painting all on it(cells, figures, etc). This is more simpler, faster to create, easier to work with.

2) Returning to your question. If you have one panel for field - you only need to remember 2 pairs of coordinates: where was first click, and where was second. In Your case - 2 pointers on panels wich was clicked will be enough. ;)

Hope this help :)

imp
+1 for a simple idea.
Suraj Chandran
+1  A: 

I agree with imp - You probably want to have a single JPanel and draw everything on that one panel.

That being said, if someone had already implemented a chessboard with 8x8 JPanels and told me to use it, I might try putting the 8x8 JPanels in a JLayeredPane and then putting a single transparent JPanel on top of everything to handle all the mouse clicks.

Still, that approach will require you to do Point arithmetic to figure out what cell is being clicked on, and I'm guessing that the point of using 8x8 JPanels was that you wanted to avoid doing that kind of arithmetic in the first place.

Joe Carnahan
+2  A: 

I don't see anything wrong with using JPanels. Here's my implementation:

First a ChessSquare, this represents one cell on the board:

public class ChessSquare extends JPanel{
    int x,y;

    public ChessSquare(int x, int y){
        super();
        this.setPreferredSize(new Dimension(50,50));
        this.setBorder(BorderFactory.createLineBorder(Color.black));
        this.x = x;
        this.y = y;
    }
}

Now the main board panel:

public class ChessPanel extends JPanel{
    JPanel positions[][] = new JPanel[8][8];
    ChessSquare move[] = new ChessSquare[2];

    public ChessPanel(){
        initComponents();
    }

    private void initComponents(){
        setLayout(new GridLayout(8,8));

        for(int i=0;i<positions.length;i++){
            for(int j=0;j<positions[i].length;j++){
                ChessSquare square = new ChessSquare(i,j);
                square.addMouseListener(new MouseListener(){
                    public void mouseClicked(MouseEvent me) {
                        ChessSquare cs = (ChessSquare)me.getComponent();
                        if(isValidMove(cs)){

                            System.out.println("Valid move!");
                            System.out.println("x1: "+move[0].x+" y1: "+move[0].y);
                            System.out.println("x2: "+move[1].x+" y2: "+move[1].y);
                            System.out.println("");

                            resetMove();
                        }
                    }

                    //Other mouse events

                });
                positions[i][j] = square;
                add(square);
            }
        }
    }

    private boolean isValidMove(ChessSquare square){
        //here you would check if the move is valid.
        if(move[0] == null){
            move[0] = square;
            return false; //first click
        }else{
            move[1] = square;
        }

        //Other chess rules go here...
        return true;
    }

    private void resetMove(){
        move = new ChessSquare[2];
    }
}

We keep a JPanel matrix to represent the board, and ChessSquare array to represent the current move. In isValidMove() we check to see if the current move is complete (both squares have been clicked, thus the move array already has one element). Once a move is complete, we reset the move and start again.

Cesar
I would also prefer individual components for the squares as it simplifies the click handling code. What it does make slightly harder is animations between squares.
Russ Hayward
For the animation between squares, check out the GlassPane. A Glass Pane is like a sheet of glass that sits atop your frame, you can use that to paint custom animations between components, in this case your individual squares.
Cesar