首先,springboot是一个很方便的东西,恩,尤其是对各种bean的管理上面,自己编写的项目难免会出现结构比较混乱的情况,而spring可以很好的解决这个问题,springboot是一个spring的快速开发项目。
springboot并没有官方对javafx的支持,但是有一个开源的项目,叫做springboot-java8-support,我们可以通过它来整合javafx。springboot就不必多说了,无论是STS还是idea都有很完善的支持,springboot-java8-support在这里:
de.roskenet
springboot-javafx-support
2.1.6
然后maven clean,maven update,这样工程就得到了更新,新导入的包就会加入项目中。
打开sceneBuilder,新建一个fxml,然后放上需要的东西,把他处理好之后移到resource文件夹里面,然后新建一个class,继承AbstractFxmlView,并且添加注解:
@FXMLView( value = "你的fxml的地址,相对于resource,注意要以斜杠/这个开头,否则找不到", css = {"你的css文件的位置,可以用多个,相对于resource"} )
然后,我会在这里进行一些在sceneBuilder不太好进行处理的ui的初始化,编写方法initUI,添加注解PostConstruct,在spring完成注入之后,就会自动调用此方法进行初始化。
特别注意:在这个库中,fxml里面不可以使用WebView,否则会导致异常!!!
spring这里面使用了很多注解,这些注解是什么,怎么起到作用的,这一点我之前做过一些了解,后续会整理出来。
其实我比较喜欢在这里处理在view里面的界面逻辑,在controller里面处理和数据相关的逻辑。
新建一个class,实现Initializable接口,然后添加方法initialize。
import de.felixroske.jfxsupport.FXMLController;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
@FXMLController
public class StartController implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {
}
}
好了,现在我们就可以和正常的javafx一样进行各种逻辑处理了,但是很多其他的ui逻辑都在view上面,因此这里可以放的基本是和数据相关的东西。
主类是需要继承AbstractJavaFxApplicationSupport这个类型,添加main方法和SpringBootApplication注解。我们使用launch方法代替SpringApplication.run,具体的可以看看AbstractJavaFxApplicationSupport的launch的实现:
/**
* Launch app.
*
* @param appClass the app class
* @param view the view
* @param args the args
*/
public static void launch(final Class extends Application> appClass,
final Class extends AbstractFxmlView> view, final String[] args);
/**
* Launch app.
*
* @param appClass the app class
* @param view the view
* @param splashScreen the splash screen
* @param args the args
*/
public static void launch(final Class extends Application> appClass,
final Class extends AbstractFxmlView> view,
final SplashScreen splashScreen, final String[] args);
/**
* Launch app.
*
* @deprecated To be more in line with javafx.application please use launch
* @param appClass the app class
* @param view the view
* @param splashScreen the splash screen
* @param args the args
*/
@Deprecated
public static void launchApp(final Class extends Application> appClass,
final Class extends AbstractFxmlView> view,
final SplashScreen splashScreen, final String[] args);
我们可以看到,至少需要一个Application的class,就是继承了AbstractJavaFxApplicationSupport这个的,然后我们还需要一个view,作为启动的界面,以及main函数的参数args,如果需要,还可以使用SplashScreen作为启动时候的闪屏,就是应用加载的时候的那个界面,你如果用过word就应该知道我的意思。
好了,点击运行,springBoot就带着javafx起来了,稍等一会你就可以看到一个javafx的窗口。
对了,如果需要对窗口做出调整,应该使用GUIState类的静态方法获取Stage,当然,这个Stage就是主窗口的Stage了。
public class Splash extends SplashScreen {
@Override
public String getImagePath() {
return "/style/title.png";
}
@Override
public Parent getParent() {
Group gp = new Group();
ImageView imageView = new ImageView(this.getClass().getResource(this.getImagePath()).toExternalForm());
gp.getChildren().add(imageView);
return gp;
}
}
继承Splash的SplashScreen,重写getParent方法,在这个方法中返回一个JavaFx的组件,这个组件就会被用到闪屏中,至于getImagePath,随便返回点什么就行。
最终,通过这个launch方法启动:
launch(Application的class,启动的FXMLView的class,new Splash(),args);
这样就有闪屏了。
为什么会有这个需求呢,是因为有的时候修改了配置,我们可以通过重启整个APP来让他重新加载切换界面或者是在线更新之后重启来激活新功能,那么怎么做到重启呢?
首先关闭javaFX打开的窗口,然后调用stop销毁ApplicationContext,然后重新启动javafx的生命周期方法init和start,因为javafx的spring-boot-support是在这两个方法里面初始化的,因此ApplicationContext会在这里重建,系统被重新启动。
而这个方法需要在AbstractJavaFxApplicationSupport的子类中实现,就是含有main的那个class。
public void relaunch(){
Platform.runLater(() -> {
getStage().close();
try {
this.stop();
this.init();
this.start(new Stage());
} catch (Exception e) {
log.error(e);
}
});
}