JavaFX fxml – 如何将Spring DI与嵌套的自定义控件一起使用?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了JavaFX fxml – 如何将Spring DI与嵌套的自定义控件一起使用?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4519字,纯文字阅读大概需要7分钟。
内容图文
![JavaFX fxml – 如何将Spring DI与嵌套的自定义控件一起使用?](/upload/InfoBanner/zyjiaocheng/725/c019c9cc3061444f8c5b17827dcd8f4b.jpg)
我已经完成了一些关于将Spring DI与Jav??aFx集成的教程,但我已经碰到了一个简单的例子没有涉及的墙(我无法弄清楚).
我想要在视图层和表示层之间进行清晰的分离.我想使用fxml定义可组合视图,使用Spring将它们连接在一起.这是一个具体的例子:
Dashboard.fxml:
<GridPane fx:id="view"
fx:controller="com.scrub.presenters.DashboardPresenter"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml">
<children>
<TransactionHistoryPresenter fx:id="transactionHistory" />
</children>
</GridPane>
Main.java:
public void start(Stage primaryStage) throws Exception{
try {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppFactory.class);
SpringFxmlLoader loader = context.getBean(SpringFxmlLoader.class);
primaryStage.setScene(new Scene((Parent)loader.load("/views/dashboard.fxml")));
primaryStage.setTitle("Hello World");
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
SpringFxmlLoader.java:
public class SpringFxmlLoader {
@Autowired
ApplicationContext context;
public Object load(String url) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource(url));
loader.setControllerFactory(new Callback<Class<?>, Object>() {
@Override
public Object call(Class<?> aClass) {
return context.getBean(aClass);
}
});
return loader.load();
} catch(Exception e) {
e.printStackTrace();
throw new RuntimeException(String.format("Failed to load FXML file '%s'", url));
}
}
}
因此,当加载DashboardPresenter时,SpringFxmlLoader正确地使用loader.setControllerFactory注入控制器.
但是,自定义TransactionHistoryPresenter控件使用新实例加载,而不是从spring上下文加载.它必须使用自己的FXMLLoader?
任何想法如何使自定义控件与Spring一起玩得很好?我真的不想让控制器/演示者手动连接它们.
解决方法:
这里的主要问题是确保在JavaFX应用程序的同一个线程上初始化Spring.这通常意味着必须在JavaFX应用程序线程上执行Spring代码;其他耗时的工作当然可以在他们自己的线程上执行.
这是我使用this tutorial和我自己的Spring Boot知识放在一起的解决方案:
@SpringBootApplication
@ImportResource("classpath:root-context.xml")
public class JavaFXSpringApplication extends Application {
private static final Logger log = LoggerFactory.getLogger(JavaFXSpringApplication.class);
private Messages messages;
private static String[] args;
@Override
public void start(final Stage primaryStage) {
// Bootstrap Spring context here.
ApplicationContext context = SpringApplication.run(JavaFXSpringApplication.class, args);
messages = context.getBean(Messages.class);
MainPaneController mainPaneController = context.getBean(MainPaneController.class);
// Create a Scene
Scene scene = new Scene((Parent) mainPaneController.getRoot());
scene.getStylesheets().add(getClass().getResource("/css/application.css").toExternalForm());
// Set the scene on the primary stage
primaryStage.setScene(scene);
// Any other shenanigans on the primary stage...
primaryStage.show();
}
public static void main(String[] args) {
JavaFXSpringApplication.args = args;
launch(args);
}
}
这个类既是JavaFX应用程序入口点又是Spring Boot初始化入口点,因此传递了varargs.导入外部配置文件可以更容易地使主类保持整洁,同时准备其他与Spring相关的东西(即设置Spring Data JPA,资源包,安全……)
在JavaFX“start”方法上,主ApplicationContext被初始化并存在.此时使用的任何bean都必须通过ApplicationContext.getBean()检索,但是所有其他带注释的bean(如果它位于此主类的后代包中)将始终可访问.
特别是,控制器在这个其他类中声明:
@Configuration
@ComponentScan
public class ApplicationConfiguration {
@Bean
public MainPaneController mainPaneController() throws IOException {
return (MainPaneController) this.loadController("path/to/MainPane.fxml");
}
protected Object loadController(String url) throws IOException {
InputStream fxmlStream = null;
try {
fxmlStream = getClass().getResourceAsStream(url);
FXMLLoader loader = new FXMLLoader();
loader.load(fxmlStream);
return loader.getController();
} finally {
if (fxmlStream != null) {
fxmlStream.close();
}
}
}
}
你可以看到任何一个Controller(我只有一个,但它可以很多)用@Bean注释,整个类是一个配置.
最后,这是MainPaneController.
public class MainPaneController {
@Autowired
private Service aService;
@PostConstruct
public void init() {
// ...stuff to do with components...
}
/*
* FXML Fields
*/
@FXML
private Node root;
@FXML
private TextArea aTextArea;
@FXML
private TextField aTextField;
@FXML
private void sayButtonAction(ActionEvent event) {
aService.doStuff(aTextArea, aTextField);
}
}
此Controller被声明为@Bean,因此可以与任何其他@Beans(或服务,组件等)进行@Autowired.现在,例如,您可以让它回答按钮按下并将在其字段上执行的逻辑委托给@Service.声明为Spring创建的控制器的任何组件都将由Spring管理,从而了解上下文.
配置非常简单直接.如果您有任何疑问,请随时询问.
内容总结
以上是互联网集市为您收集整理的JavaFX fxml – 如何将Spring DI与嵌套的自定义控件一起使用?全部内容,希望文章能够帮你解决JavaFX fxml – 如何将Spring DI与嵌套的自定义控件一起使用?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。