JavaFX: Why do I have to press the button several times before the background changes?

poisn :

In my programm I want to switch dark mode on and off via a MenuItem. And it's is working, but I've a little problem and I don't understand what causes this problem.

The problem is, that I've to select the CheckMenuItem serveral times before the selectedProperty is doing something.

If you run my mvce, you should see it (I think you have to click it 3 times). But after the selectedProperty was active for the first time, it works without any problems until you restart the application.

MVCE

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.MenuButton;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class DarkModeMVCE extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {

        BorderPane pane = new BorderPane();
        Scene scene = new Scene(pane, 500, 500);

        MenuButton menuButton = new MenuButton("Menu");
        CheckMenuItem checkMenuItem = new CheckMenuItem("Darkmode");
        checkMenuItem.setSelected(false);

        checkMenuItem.setOnAction(aE -> checkMenuItem.selectedProperty().addListener((obs, wasSelected, isSelected) -> {

            if (isSelected) {
                pane.setStyle("-fx-background-color: black");
            }
            else {
                pane.setStyle("-fx-background-color: white");
            }

        }));

        menuButton.getItems().add(checkMenuItem);

        pane.setCenter(menuButton);

        primaryStage.setScene(scene);
        primaryStage.setTitle("MVCE");
        primaryStage.show();
    }
}

Can anyone please explain why this is happening? Is this a bug or an error in the code?

Ahmed Emad :

setOnAction() listener listen to any action applies on the MenuItem so when you click the menuItem it execute the code inside the listener
which at this point assign a new listener to the property of selection on the menuItem which gonna listen if the menuItem is gonna be selected or not next time any action is applied so the first action is not counted the next you do is deselect the menuItem whchi in your case do nothing and re-select it again make the desired action so no need to make two listener to the same property you can just make a listener to the change of the selection property

checkMenuItem.selectedProperty().addListener((obs, wasSelected, isSelected) -> {

    if (isSelected) {
        pane.setStyle("-fx-background-color: black");
    }
    else {
        pane.setStyle("-fx-background-color: white");
    }

});

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=307253&siteId=1