首页 > 解决方案 > 选择/取消选择检查菜单按钮在 javafx 中给出空指针异常

问题描述

我正在尝试使用 javafx 12 创建一个简单的 GUI。除了我尝试将侦听器添加到 CheckMenuItem 时,一切正常,尽管执行了操作,但抛出了 NullPointerException,但我不明白为什么以及抛出的原因例外。如果有人可以提供帮助,那就太棒了。这是我正在使用的代码:

这是控制器类,在 fxml 中没有指定它,因为当我使用 loader.setController(myController); 之类的东西创建舞台时,它设置了一些变量;(它的目的是)。另外 opt 是由另一个窗口设置的,其中一些选项可以打开这个窗口。所以 opt 实际上可以是真或假,具体取决于用户之前选择的内容。

private boolean opt;
@FXML Menu map_menu;
@FXML CheckMenuItem menuOpt;
public void initialize(URL arg0, ResourceBundle arg1) {
if (opt == true) {
        menuOpt.setSelected(true);
        map_menu.setVisible(true);
    } else {
        menuOpt.setSelected(false);
        map_menu.setVisible(false);
    }

    menuOpt.selectedProperty().addListener(new ChangeListener<Boolean>() {

        @Override
        public void changed(ObservableValue<? extends Boolean> ov, Boolean oldval, Boolean newval) {
            opt = newval.booleanValue();
            map_menu.setVisible(newval.booleanValue());
        }

    });

}

fxml 文件:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.CheckMenuItem?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="900.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <MenuBar fx:id="menuBar" layoutY="2.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
        <menus>
          <Menu fx:id="menuFile" mnemonicParsing="false" text="File">
            <items>
                  <MenuItem mnemonicParsing="false" text="Change files" />
              <MenuItem mnemonicParsing="false" text="Close" />
            </items>
          </Menu>
            <Menu fx:id="menuView" mnemonicParsing="false" text="View">
              <items>
                <MenuItem fx:id="menuSwitchBasic" mnemonicParsing="false" onAction="#switch_viewToBasic" text="Switch to basic view" />
                  <MenuItem fx:id="menuSwitchDebug" mnemonicParsing="false" onAction="#switch_viewToDebug" text="Switch to debug view" />
                  <CheckMenuItem fx:id="menuOpt" mnemonicParsing="false" text="Optional features" />
              </items>
            </Menu>
            <Menu fx:id="map_menu" mnemonicParsing="false" text="Map">
              <items>
                <MenuItem mnemonicParsing="false" text="Change map" />
                  <MenuItem mnemonicParsing="false" text="Create new map" />
                  <MenuItem mnemonicParsing="false" text="Edit map" />
              </items>
            </Menu>
          <Menu fx:id="menuHelp" mnemonicParsing="false" text="Help">
            <items>
              <MenuItem mnemonicParsing="false" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
      <AnchorPane fx:id="anchorPane" layoutX="6.0" layoutY="27.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="27.0" />

   </children>
</AnchorPane>

打印堆栈跟踪:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.controls/javafx.scene.control.skin.MenuButtonSkinBase.lambda$new$7(MenuButtonSkinBase.java:188)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:835)

更新:我尝试删除侦听器代码并添加一个要在操作上调用的方法,而不是像这样:

@FXML void opt_menu() {
    if (menuOpt.isSelected()) {
        opt = true;
        map_menu.setDisable(false);
        map_menu.setVisible(true);  
    } else {
        opt = false;
        map_menu.setDisable(true);
        map_menu.setVisible(false);
    }
}

不幸的是,没有任何改变。请注意,当我单击菜单时,操作已正确执行(另一个菜单 map_menu 已正确隐藏并且应用程序继续运行)但 eclipse 仍然给我这个 NullPointerException。我尝试在其他线程上进行一些研究,有人说这可能是一个焦点问题?我不确定它是否也适用于菜单。

(PS:我没有包含更多代码,因为它与这个问题完全无关,事实上如果我不触摸菜单一切正常)

更新 2:我尝试用常规 MenuItem 替换 CheckMenuItem 但问题仍然存在

标签: javajavafxmenuitem

解决方案


发布的代码不是mre,这留下了很多猜测。由于文件未指定控制器
,因此不清楚如何调用控制器。fxml您需要使用标签fx:controller=" . . .Controller "内的指定它。AnchorPane

控制器(实现Initializable)需要包含定义在fxml: public void switch_viewToBasic(ActionEvent e)public void switch_viewToDebug(ActionEvent e)

旁注:当initialize(...)被调用时opt总是假的,所以if (opt == true)什么也不做。


推荐阅读