【问题标题】:JavaFX menubutton throws exceptionJavaFX 菜单按钮抛出异常
【发布时间】:2020-05-01 07:43:41
【问题描述】:

我在 fxml 中使用 MenuButton 在选项卡之间切换。问题是,menubuttons 抛出异常,但如果我将它更改为一个简单的按钮,它不会。 这是我的 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>

在我的控制器类中:

 @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");
    }

我得到的例外:

"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

编辑:这是我的 App 类代码,它扩展了应用程序。 应用类:

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

}

【问题讨论】:

  • 在方法中添加ActionEvent event参数是否有效?
  • 我得到了同样的例外。选项卡切换,有无 ActionEvent 参数,但总是抛出异常。
  • 您发布了整个堆栈跟踪吗?还是您只发布了堆栈跟踪的第一部分?如果您没有发布整个堆栈跟踪,请edit您的问题并发布您获得的整个堆栈跟踪。
  • 不确定我是否正确,但尝试添加以下 3 行:MenuItem menuItem1 = new MenuItem("blabla"); 和:``` MenuButton menuButton = new MenuButton("Select", null, menuItem1, menuItem2, menuItem3 );```然后在我的方法中调用menuButton.hide();。仍然抛出异常。

标签: java javafx fxml


【解决方案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();
  }
}

哪些输出:

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)

至少有两种简单的方法可以“修复”NPE:

  1. 在更改Scene 的根之前隐藏MenuButton。

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

    如果您使用 FXML,则需要将 MenuButton 注入 FXML 控制器实例。这是通过在 FXML 文件中为元素提供 fx:id="foo" 属性并向控制器添加 @FXML private MenuButton foo; 字段来实现的。然后在更改Scene 的根之前调用foo.hide()。

    有关 FXML 的更多信息,请参阅 Introduction to FXML。

  2. 更改Stage 的Scene,而不是更改Scene 的根。

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

示例和解决方案均使用 JavaFX 14.0.1 进行了测试。


1.请注意,您应该在问题中提供此类示例。

【讨论】:

  • 刚刚用我的应用类编辑了我的问题。一旦我将它们添加到 fxml 文件中,你能看一下并解释为什么我需要这些按钮吗?
  • 请注意,我理解您要我解释的内容。注意我编辑了我的答案以解决您对 FXML 的使用(请参阅解决方案 #1)。
  • 我的意思是我的 App 类看起来和你的完全不同。我没有对那里的按钮做任何事情,因为它们在我的 fxml 文件中,我只是简单地加载我的 fxml 文件,设置它的根并启动它。
  • 糟糕,我就是这个意思。感谢您指出我的错误;修好了。
  • 提交单独的JDK-8244234 以不要忘记.. 奇怪的是,它的相关问题往往会在相当短的时间内冒出来:)
猜你喜欢
  • 1970-01-01
  • 2017-03-04
  • 1970-01-01
  • 2018-09-23
  • 2020-10-20
  • 2011-10-12
  • 2013-05-24
  • 2019-03-25
相关资源
最近更新 更多