Search code examples
javajavafxlocal-variables

How can I make buttons in a for loop with a lamda expression for each?


I'm trying to make a hangman game in javafx. So naturally, instead of making 26 individual buttons, I am trying to use a for loop to create each button. I am putting them into an ArrayList called alphabet and adding them to a flowPane. The trouble I am running into is when I try to set the action of each button to go to a function with the parameter of it's letter that checks to see if the letter has been used or if it is in the word.

All the instantiations:

ArrayList<Button> alphabet = new ArrayList<Button>();
FlowPane keyboard = new FlowPane();

letterGuess function (currently empty)

public void letterGuess(char letter) {

}

The code in my launch() function:

char letter;
for(int i=0 ; i<26 ; i++) {
    letter = (char) (i+65);
    alphabet.add(new Button("" + letter));
    keyboard.getChildren().add(alphabet.get(i));
    alphabet.get(i).setOnAction(e -> letterGuess(letter));
}

I expect the code to run through without an error and successfully pass letter to letterGuess() for each button. The error I get is at letter in alphabet.get(i).setOnAction(e -> letterGuess(letter)); The error says: Local variable letter defined in an enclosing scope must be final or effectively final


Solution

  • The issue is that you're declaring letter outside the loop and thus trying to change it's value inside the loop. This means the lambda can't use it since it isn't a final or "effectively" final.

    You can solve this by declaring the char as new within the loop.

    Here is another way you could write the loop which will work fine:

        for (int i = 0; i < 26; i++) {
            char letter = (char) (i + 65);
            Button button = new Button(String.valueOf(letter));
            button.setOnAction(event -> letterGuess(letter));
            alphabet.add(button);
        }
    

    You could also declare letter as final within the loop, but it is not necessary in this case. Because letter is only assigned a value once in the loop, it is effectively final and the lamba knows it.