java - NullPointerException 从 FXML 加载场景图,与 Spring 集成
问题描述
我想为我的 JavaFX 应用程序构建一个控制器,它会自动将 FXML 文件“view.fxml”加载到成员“父根”中并采用构造函数参数(在本例中为“字符串消息”)。
我让它工作得很好,但后来我尝试使用 Spring 实例化一个 DemoController 实例,我收到“NullPointerException:Root 不能为空”。这让我很恼火,因为使用 Spring 的 bean 实例化似乎工作得很好,但它没有正确加载 FXML。我唯一的猜测是目录结构可能搞砸了,但我无法修复它,我会非常感谢任何帮助:)
主.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
DemoController myController = (DemoController) context.getBean("myController");
primaryStage.setScene(new Scene(myController.getRoot()));
primaryStage.setTitle("Game of Life");
primaryStage.show();
((ClassPathXmlApplicationContext) context).close();
}
}
FXMLController.java
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
public abstract class FXMLController implements Initializable {
protected Parent root;
protected String fxmlFilePath;
public void afterPropertiesSet() throws Exception {
loadFXML();
}
protected final void loadFXML() throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlFilePath));
loader.setController(this);
this.root = loader.load();
}
public Parent getRoot() {
return root;
}
public void setFxmlFilePath(String fxmlFilePath) {
this.fxmlFilePath = fxmlFilePath;
}
}
演示控制器.java
import java.net.URL;
import java.util.ResourceBundle;
public class DemoController extends FXMLController {
public DemoController(String message) {
System.out.println(message);
}
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
System.out.println("initializing");
}
}
豆类.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id = "myController" class = "DemoController">
<constructor-arg value = "message"/>
<property name = "fxmlFilePath" value = "/view.fxml"/>
</bean>
</beans>
视图.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns:fx="http://javafx.com/fxml/1">
<!-- TODO Add Nodes -->
</AnchorPane>
目录结构
- 源代码
- 豆类.xml
- 视图.fxml
- (默认包)
- 演示控制器.java
- FXMLController.java
- 主.java
控制台输出
message
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException: Root cannot be null
at javafx.scene.Scene.<init>(Scene.java:336)
at javafx.scene.Scene.<init>(Scene.java:194)
at Main.start(Main.java:21)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
... 1 more
Exception running application Main
代码的简要概述:
- 主要搭建JavaFX环境,使用Spring实例化一个DemoController。它显示控制器给出的场景图。
- FXMLController 是一个抽象类,它封装了 FXML 文件的加载,并为场景图提供了一个 getter 方法(getRoot())。
- DemoController 扩展了 FXMLController 并没有增加太多。
- Beans.xml 为 Spring 提供了控制器的必要配置信息。
- view.fxml 只有一个 AnchorPane 并且基本上是空的。
解决方案
你没有实现InitializingBean
,所以afterPropertiesSet
永远不会被调用。实现这个接口应该可以解决这个问题:
public abstract class FXMLController implements Initializable, InitializingBean {
...
@Override
public void afterPropertiesSet() throws Exception {
loadFXML();
}
...
}
推荐阅读
- google-chrome-extension - 增加或减少 url 参数的扩展
- scala - 将被拒绝的记录保存在另一个 rdd
- java - UDP:关于接收响应如何工作的问题
- c++ - istream 运算符跳过空格字符
- c++ - 从 Eigen 中的向量/矩阵中提取元素
- numpy - 用 complex64 进行 LU 分解的数值精度
- git - 用于搜索提交消息的 Git 别名
- javascript - LocalForage async/await getItem() 等待 2 个变量然后完成加载
- c# - 如何创建跨度
在类型 T 的单个变量(字段或 ref 参数)上长度为 1 - c# - 无法为应用程序池创建磁盘缓存子目录