-2

I am using JavaFX to create a minesweeper game. I have a lambda expression where (for now) when I press a button from the grid of buttons, it sets the text of the button to be the location in the 2D array. I am getting the error "Local variable text defined in an enclosing scope must be final or effectively final."

I understand that the variables I am using in the lambda expression cant be done because they have to be final outside the expression. but I cant figure out how to get around that.

static Stage stage;
Button[][] buttonGrid;

public void start(Stage primaryStage) throws Exception {
    SetSettings.readSettings();
    GridPane gridpane = new GridPane();

    int gridSize = Minesweeper.gridSize;
    buttonGrid = new Button[gridSize][gridSize];
    for (int i = 0; i < gridSize; i++) {
        for (int j = 0; j < gridSize; j++) {
            buttonGrid[i][j] = new Button();
            GridPane.setConstraints(buttonGrid[i][j], j, i);

        }
    }
    String text = "";
    for (int i = 0; i < gridSize; i++) {
        for (int j = 0; j < gridSize; j++) {
            text += i + "" + j;
            buttonGrid[i][j].setOnAction(e -> {
                buttonGrid[i][j].setText(text);
                text = "";

            });
            gridpane.getChildren().add(buttonGrid[i][j]);
        }
    }

    stage = primaryStage;
    primaryStage.setOnCloseRequest(e -> {
        e.consume();
        ConfirmExit.display("Exit", "Are you sure you want to quit this game?");
    });
    primaryStage.setTitle("Minesweeper");
    stage.getIcons().add(new Image("/Logo.jpg"));
    Scene scene = new Scene(gridpane, 600, 500);
    primaryStage.setScene(scene);
    primaryStage.show();
}


public static void main(String[] args) {
    launch(args);
}

It is flagging i, j, and text in the same error.

gridSize is the size of my grid for minesweeper. buttonGrid is the grid of buttons I am placing in the gridPane.

I saw a solution on stackoverflow to set these variables as global, but that did not work.

Saksham Goyal
  • 145
  • 1
  • 11
  • 1
    There is no "global" in java and even if you convert the variables to fields this would not work. I'm not sure what you're trying to achieve here, but even assuming you copy the results to new variables in the inner loop/create a field, the logic seems weird: The first time a button would be clicked the text of that button would be changed to contain all the combinations of indices, for all clicks that happen after the text would be removed... – fabian Apr 16 '20 at 00:57
  • @fabian I have added my full code. Hope this helps you understand what I'm doing – Saksham Goyal Apr 16 '20 at 01:29

1 Answers1

2

Just move the definition of text inside the loop (so you define a new, effectively final, variable on each iteration of the loop). You can also define a Button variable in the same way, to avoid referencing i and j:

for (int i = 0; i < gridSize; i++) {
    for (int j = 0; j < gridSize; j++) {
        String text = i + "" + j;
        Button button = buttonGrid[i][j] ;
        button.setOnAction(e -> {
            button.setText(text);    
        });
        gridpane.getChildren().add(buttonGrid[i][j]);
    }
}
James_D
  • 201,275
  • 16
  • 291
  • 322
  • then how do i add the value of i and j if I make a new button? – Saksham Goyal Apr 16 '20 at 00:34
  • @SakshamGoyal I don't understand what you mean by "add the value of `i` and `j`". And this code doesn't create any new buttons. – James_D Apr 16 '20 at 00:36
  • added full code to OP. do you understand what im trying to do npw? – Saksham Goyal Apr 16 '20 at 01:30
  • @SakshamGoyal I don’t really understand what you’re trying to do with the string concatenation, or why you’re resetting `text` in the event handler. It’s not clear what you expect to happen there. What text do you want to appear in button (I,j) when it’s pressed? – James_D Apr 16 '20 at 01:36
  • You said: *”when I press a button from the grid of buttons, it sets the text to be the location in the 2D array”*, which is what the code I posted does. – James_D Apr 16 '20 at 01:47
  • the position of the button in the buttonGrid. so if I press the top left button, the text should say "00" – Saksham Goyal Apr 16 '20 at 01:47
  • What I understand from your code is that its creating a copy of a button in buttonGrid and settings its action. but then you are adding the original button without making buttonGrid[i][j] into that copy – Saksham Goyal Apr 16 '20 at 01:50
  • @SakshamGoyal Huh? How am I “creating a copy of a button”? – James_D Apr 16 '20 at 01:52
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/211774/discussion-between-saksham-goyal-and-james-d). – Saksham Goyal Apr 16 '20 at 01:57