2

I'm trying to write my first Swing app, it is a simple chess engine in Java. I've made a grid of JButtons to represent squares. Looks ok, but I've come across a problem when trying to add ActionListeners to each square. I want to get squares co-ordinates and print it to console when its clicked. This is what I tried(I guess I don't really understand how ActionListeners work):

// chessBoardSquares[][] is an 8x8 array of Jbuttons

for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {

            chessBoardSquares[i][j].addActionListener(new ActionListener(){

                @Override
                public void actionPerformed(ActionEvent e) {

                    System.out.println("x: "+i+"y: "+j);

                }

            });
        }
    }
Christophe Biocca
  • 3,388
  • 1
  • 23
  • 24
EasternDude
  • 413
  • 4
  • 16

2 Answers2

3

You need to use either fields or final local variables inside an anonymous inner class.

for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
        final int finalI = i;
        final int finalJ = j;

        chessBoardSquares[i][j].addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("x: " + finalI +"y: " + finalJ);
            }
        });
    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
2

Starting from Java 8, you can have use both final and effectively final variables inside anonymous classes (or lambda expressions). An effectively final variable is not declared as final, but its value is never changed.

Your code could be written like this:

for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {

        int finalI = i; // no final modifier
        int finalJ = j;

        chessBoardSquares[i][j].addActionListener(e -> {
            System.out.println("x: " + finalI + "y: " + finalJ);
        });
    }
}
Bubletan
  • 3,833
  • 6
  • 25
  • 33