java - JavaFX 预加载器问题
问题描述
你好亲爱的 Stackoverflow,
我有几个关于 JavaFX 类 Preloader 的问题。经过长期的研究,我没有找到任何合适的解决方案来解决我的问题,我认为这并不是我的代码的问题,而是 JavaFX 本身在 Preloader 类方面的限制。
让我直截了当地说:难道不能使用 FXML 来定义 Preloader 的设计吗?有趣的是,所有教程仅通过从类中创建新实例来指导您创建预加载器。(ProgressBar progressBar = new ProgressBar(); 即)
所以,让我们用这个示例代码来和我一起测试一下:
测试预加载器:
import com.sun.javafx.application.LauncherImpl;
import javafx.application.Preloader;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class TestPreloader extends Preloader {
@FXML
ProgressBar progressBar;
public static void main(String[] args) {
LauncherImpl.launchApplication(TestApplication.class, TestPreloader.class, args);
}
public void initialize() {
System.out.println("initialize printed");
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.initStyle(StageStyle.TRANSPARENT);
Parent root = FXMLLoader.load(getClass().getResource("preloader.fxml"));
Scene scene = new Scene(root);
scene.setFill(Color.TRANSPARENT);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.centerOnScreen();
primaryStage.show();
}
@Override
public void handleProgressNotification(ProgressNotification progressNotification) {
// progressBar.setProgress(progressNotification.getProgress());
}
@Override
public void handleStateChangeNotification(StateChangeNotification notification) {
System.out.println(notification.getType().toString());
switch (notification.getType()) {
case BEFORE_START:
//progressBar.setProgress(1);
break;
case BEFORE_LOAD: //this is where the TestApplication class will be constructed
//progressBar.setProgress(1);
break;
case BEFORE_INIT:
//progressBar.setProgress(1);
break;
}
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="TestPreloader">
<children>
<ProgressBar fx:id="progressBar" layoutX="174.0" layoutY="141.0" prefWidth="200.0" progress="0.0" />
</children>
</AnchorPane>
测试应用
import javafx.application.Application;
import javafx.stage.Stage;
public class TestApplication extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
System.out.println("Application started!");
}
}
如果您开始,则输出按以下顺序排列:
initialize printed
BEFORE_LOAD
BEFORE_INIT
BEFORE_START
Application started!
现在,正如您所看到的,initialize() 方法被直接调用,然后预加载器的状态发生变化,因此在每次更改时都会弹出通知 - 到目前为止一切都很好。
然而困扰我的是,如果我在初始化方法中调用 progressBar#setProgress ,进度实际上会设置为 1 并且不会抛出任何错误。尽管状态在预加载器初始化之后出现,但 NullPointers 也会出现。
要理解我的意思,请在 handleStateNotification 下取消注释 setProgress(在 BEFORE_LOAD 语句下对我来说最有意义),您会看到 NullPointerException 弹出。
现在,为什么会发生?我能做些什么来解决这个问题?这对我来说没有任何意义。如果 Preloader 初始化了,ProgresssBar 不为 null,那之后怎么转为 null 呢?也许也许有一个单独使用的自己的类的新实例?但这对我来说也没有意义。你为什么会有那个?
我在这个问题上停留了几天,我的意思是我可以去一个时间轴并“硬编码”它,但是我想了解导致这些问题的原因。
TLDR;使用 Preloader 类初始化应用程序后 ProgressBar 变为 null,是什么原因造成的,我该怎么办?
编辑:似乎课程没有在某处重建,idk我真的卡住了哈哈
解决方案
当 FXMLLoader 加载您的 FXML 文件时,它会创建指定控制器的新实例。然而,这并不是我们想要的结果。接收状态回调的对象应该是 FXML 窗口的控制器。
用FXMLLoader.load(...)
_
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("preloader.fxml"));
fxmlLoader.setController(this);
Parent root = fxmlLoader.load();
并从 FXML 中删除控制器属性,导致 FXMLLoader 使用给定的控制器实例(接收状态回调的实例)而不是构造指定控制器类的新实例。
推荐阅读
- sql - 以编程方式检查 SQL 的正确性
- c# - 我想获取位置更改,但我在 GoogleApiClient 中收到 JNI DETECTED ERROR IN APPLICATION
- swift - 有没有办法取消 DispatchQueue concurrentPerform 操作?
- javascript - 递归返回对象数组和嵌套对象键
- html - 当屏幕尺寸减小时,为什么我的图像没有响应?
- json - 从具有 JSON 列表的 JSON 中提取键值?
- php - while 循环中的输出缓冲从模板呈现损坏的 html
- r - 按组将一个变量分成多个
- c# - 根据类中的字段对列表进行排序
- python - Python - 在后台监听键绑定