JavaFX:为什么在背景更改之前我必须多次按下按钮?

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

在我的程序中,我想通过 MenuItem 打开和关闭暗模式。它正在运行,但我遇到了一个小问题,我不明白是什么原因导致了这个问题。

问题是,在 selectedProperty 执行某些操作之前,我必须 select CheckMenuItem 几次。

如果你运行我的mvce,你应该能看到它(我想你必须点击它3次)。 但是在 selectedProperty 第一次激活后,它可以正常工作,直到您重新启动应用程序。

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();
    }
}

谁能解释一下为什么会这样? 这是错误还是代码错误?

setOnAction() 侦听器侦听应用于 MenuItem 的任何操作,因此当您单击 menuItem 时它会执行侦听器中的代码
这在这一点上为 menuItem 上的 selection 的 属性 分配一个新的侦听器,如果 menuItem 将被 selected 或不被 下次监听 应用任何操作,因此不计算第一个操作接下来你做的是 deselect menuItem whchi 在你的情况下什么都不做然后重新 select 它再次做出所需的动作所以没有需要让两个监听器监听相同的 属性 你可以只监听 selection 属性

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

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

});

这是实现此目的的简单方法:-)

    checkMenuItem.setOnAction(event -> {

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

    });