前言:现在脱离Spring-Boot
已经不会写代码了。
之前写过一篇依赖
springboot-javafx-support
,JavaFX与Spring Boot的文章,
springboot-javafx-support
提供了一些注解,封装了一些功能,若不依赖springboot-javafx-support
,使用原生代码,如何使JavaFX与Spring Boot 结合呢?
- 引入依赖(使用的jdk8,内置了javafx,若使用高版本需要手动加入javafx的依赖)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 编写Spring的启动类与JavaFx的启动类(可以合二为一)
- 声明了
@SpringBootApplication
的类(MainApplication
)为主入口,通过该类启动JavaFX程序。 - JavaFX的启动类(
JavaFxApplication
)的init方法中启动Spring Boot - 为了将JavaFX的东西纳入Spring,JavaFX的启动类(
JavaFxApplication
)的start方法中,发布一个事件,在事件监听中启动JavaFX的Stage
- 声明了
package com.podigua;
import javafx.application.Application;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring 启动类 main方法中启动JavaFX
* @author: podigua
* @create: 2021-03-19 17:32
**/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
Application.launch(JavaFxApplication.class,args);
}
}
package com.podigua;
import com.podigua.event.StageReadyEvent;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
/**
* init方法中启动Spring程序,并记录上下问
* @author: podigua
* @create: 2021-03-19 17:34
**/
public class JavaFxApplication extends Application {
private static ConfigurableApplicationContext applicationContext;
@Override
public void init() {
applicationContext = new SpringApplicationBuilder(MainApplication.class).run();
}
@Override
public void start(Stage stage){
applicationContext.publishEvent(new StageReadyEvent(stage));
}
@Override
public void stop() {
applicationContext.close();
Platform.exit();
}
}
- 定义事件与监听
package com.podigua.event;
import javafx.stage.Stage;
import org.springframework.context.ApplicationEvent;
/**
* Stage 就绪事件
* @author: podigua
* @create: 2021-03-19 17:38
**/
public class StageReadyEvent extends ApplicationEvent {
public StageReadyEvent(Stage stage) {
super(stage);
}
public Stage getStage() {
return (Stage) getSource();
}
}
package com.podigua.listener;
import com.podigua.event.StageReadyEvent;
import com.podigua.service.FxmlService;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;
/**
* Stage就绪监听中展示Stage
* @author: podigua
* @create: 2021-03-19 17:32
**/
@Service
public class StageReadyListener implements ApplicationListener<StageReadyEvent> {
private final FxmlService fxmlService;
public StageReadyListener(FxmlService fxmlService) {
this.fxmlService = fxmlService;
}
@Override
public void onApplicationEvent(StageReadyEvent event) {
Stage stage = event.getStage();
Parent parent = fxmlService.getByPath("/views/main.fxml");
Scene scene=new Scene(parent,800,600);
stage.setScene(scene);
stage.setTitle("title");
stage.sizeToScene();
stage.show();
}
}
- 加载fxml与将controller纳入spring
StageReadyListener
的启动代码中有以下代码,加载fxml,并将controller纳入了spring容器
Parent parent = fxmlService.getByPath("/views/main.fxml");
- fxmlService 内容
@Service
public class FxmlServiceImpl implements FxmlService {
private final ApplicationContext applicationContext;
public FxmlServiceImpl(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public <T extends Parent> T getByPath(String path){
try {
FXMLLoader loader = new FXMLLoader(new ClassPathResource(path).getURL());
//获取在fxml中的指定的controller(将controller纳入了spring)
loader.setControllerFactory(clazz -> applicationContext.getBean(clazz));
return loader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
- controller的代码,controller 中可以使用spring中的任何bean
@Service
public class MainController {
@FXML
public Label text;
public void click(ActionEvent event) {
text.setText("hello JavaFX");
}
}
- fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="com.podigua.controller.MainController"
prefHeight="400.0" prefWidth="600.0">
<Button onAction="#click" text="测试"/>
<Label fx:id="text" text="hello"/>
</VBox>
此功能的关键点,
- JavaFx的Application中启动Spring
- 不在JavaFx的Application的start方法中直接展示Stage,而是先发布一个事件,在事件监听中展示Stage
- 获取xml时,指定controller的获取方法(从ApplicationContext的getBean方法获取)
代码github地址