JavaFX 菜单按钮抛出异常
JavaFX menubutton throws exception
我在 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>
在我的控制器中 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");
}
我得到的异常是:
"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\javafx-base-14-win.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14-win.jar;D:\IntelliJ IDEA 2019.3.4\projects\proba\target\classes;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14-win.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-base\javafx-base-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-fxml\javafx-fxml-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-fxml\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(MenuButtonSkinBase.java:198)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(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(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
Process finished with exit code 0
编辑:这是我的应用程序代码 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();
}
}
你的错误可以用这个最小的例子重现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(MenuButtonSkinBase.java:198)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(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(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
至少有两种 "fix" NPE 的简单方法:
在更改 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。
更改 Stage
的 Scene
而不是更改 Scene
的根。
StackPane root = new StackPane(new Label("Hello, World!"));
primaryStage.setScene(new Scene(root, 500, 300));
示例和解决方案均使用 JavaFX 14.0.1 进行了测试。
1.请注意,此类示例应该由您在问题中提供。
我在 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>
在我的控制器中 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");
}
我得到的异常是:
"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\javafx-base-14-win.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14-win.jar;D:\IntelliJ IDEA 2019.3.4\projects\proba\target\classes;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-controls\javafx-controls-14-win.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-graphics\javafx-graphics-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-base\javafx-base-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-fxml\javafx-fxml-14.jar;C:\Users\tarbe\.m2\repository\org\openjfx\javafx-fxml\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(MenuButtonSkinBase.java:198)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(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(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
Process finished with exit code 0
编辑:这是我的应用程序代码 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();
}
}
你的错误可以用这个最小的例子重现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(MenuButtonSkinBase.java:198)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(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(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
至少有两种 "fix" NPE 的简单方法:
在更改
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。
更改
Stage
的Scene
而不是更改Scene
的根。StackPane root = new StackPane(new Label("Hello, World!")); primaryStage.setScene(new Scene(root, 500, 300));
示例和解决方案均使用 JavaFX 14.0.1 进行了测试。
1.请注意,此类示例应该由您在问题中提供。