简体   繁体   English

JavaFX 菜单按钮抛出异常

[英]JavaFX menubutton throws exception

I'm using MenuButton in fxml to switch between tabs.我在 fxml 中使用 MenuButton 在选项卡之间切换。 The problem is, the menubuttons throw exceptions, but if I change it to a simple button, it doesn't.问题是,菜单按钮会引发异常,但如果我将其更改为简单按钮,则不会。 Here's my fxml code:这是我的 fxml 代码:

 <MenuButton mnemonicParsing="false" prefHeight="27.0" prefWidth="101.0" style="-fx-background-color: #666666;" text="Select menu" textFill="WHITE" GridPane.columnIndex="4">
<items>
<MenuItem mnemonicParsing="false" onAction="#switchToMoney" text="1" />
<MenuItem mnemonicParsing="false" onAction="#switchToWeight" text="2" />
<MenuItem mnemonicParsing="false" onAction="#switchToTemperature" text="3" />
</items>
</MenuButton>

In my controller class:在我的 controller class 中:

 @FXML
    private void switchToMoney() throws IOException {
        App.setRoot("money");
    }

    @FXML
    private void switchToWeight() throws IOException {
        App.setRoot("weight");
    }

    @FXML
    private void switchToTemperature() throws IOException {
        App.setRoot("temperature");
    }

and the exception I get:我得到的例外是:

"C:\Program Files\Java\jdk-14\bin\java.exe" --add-modules javafx.base,javafx.graphics --add-reads javafx.base=ALL-UNNAMED --add-reads javafx.graphics=ALL-UNNAMED "-javaagent:D:\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=64566:D:\IntelliJ IDEA 2019.3.4\bin" -Dfile.encoding=UTF-8 -p "C:\Users\tarbe\.m2\repository\org\openjfx\javafx-base\14\javafx-base-14-win.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-graphics\14\javafx-graphics-14-win.jar;D:\IntelliJ IDEA 2019.3.4\projects\proba\target\classes;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-controls\14\javafx-controls-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-controls\14\javafx-controls-14-win.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-graphics\14\javafx-graphics-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-base\14\javafx-base-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-fxml\14\javafx-fxml-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-fxml\14\javafx-fxml-14-win.jar" -m org.alkfejl/org.alkfejl.App
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:222)
    at javafx.controls/javafx.scene.control.skin.MenuButtonSkinBase.lambda$new$7(MenuButtonSkinBase.java:198)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    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:832)

Process finished with exit code 0

EDIT: Here's my code of the App class, which extends the Application.编辑:这是我的应用程序 class 的代码,它扩展了应用程序。 the App class:应用 class:

public class App extends Application {

    private static Scene scene;

    @Override
    public void start(Stage stage) throws IOException {
        scene = new Scene(loadFXML("general"));
        stage.setTitle("Calculator");
        stage.setScene(scene);
        stage.show();
    }

    static void setRoot(String fxml) throws IOException {
        scene.setRoot(loadFXML(fxml));
    }

    private static Parent loadFXML(String fxml) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
        return fxmlLoader.load();
    }

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

}

Your error can be reproduced with this minimal example 1 :你的错误可以用这个最小的例子1重现:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) {
    MenuButton btn = new MenuButton("Switch...");

    MenuItem item = new MenuItem("To 'Hello, World!'");
    item.setOnAction(
        e -> {
          StackPane root = new StackPane(new Label("Hello, World!"));
          primaryStage.getScene().setRoot(root);
        });
    btn.getItems().add(item);

    primaryStage.setScene(new Scene(new StackPane(btn), 500, 300));
    primaryStage.show();
  }
}

Which outputs:哪个输出:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:222)
    at javafx.controls/javafx.scene.control.skin.MenuButtonSkinBase.lambda$new$7(MenuButtonSkinBase.java:198)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    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:832)

There are at least two simple ways to "fix" the NPE:至少有两种简单的方法可以“修复”NPE:

  1. Hide the MenuButton before changing the root of the Scene .在更改Scene的根之前隐藏MenuButton

     StackPane root = new StackPane(new Label("Hello, World;")). btn;hide(). primaryStage.getScene();setRoot(root);

    If you're using FXML then you'll need to inject the MenuButton into the FXML controller instance.如果您使用 FXML,则需要将MenuButton注入 FXML controller 实例。 This is accomplished by giving the element an fx:id="foo" attribute in the FXML file and adding an @FXML private MenuButton foo;这是通过在 FXML 文件中给元素一个fx:id="foo"属性并添加一个@FXML private MenuButton foo; field to the controller.字段到 controller。 Then you would invoke foo.hide() before changing the root of the Scene .然后,您将在更改Scene的根之前调用foo.hide()

    See Introduction to FXML for more information about FXML.有关FXML 的更多信息,请参阅 FXML 简介

  2. Change the Scene of the Stage instead of changing the root of the Scene .更改StageScene而不是更改Scene的根。

     StackPane root = new StackPane(new Label("Hello, World;")). primaryStage,setScene(new Scene(root, 500; 300));

Both the example and solutions were tested using JavaFX 14.0.1.示例和解决方案均使用 JavaFX 14.0.1 进行了测试。


1. Note this sort of example is what should be provided by you, in the question. 1.请注意,您应该在问题中提供此类示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM