JavaFX预加载程序问题
你好,亲爱的Stackoverflow 关于JavaFX类预加载程序,我有几个问题。 经过长期的研究,我还没有找到任何解决问题的正确方法,我认为这并不是我的代码的问题,而是JavaFX本身在预加载类方面的局限性 让我直截了当地谈谈我的观点:难道不能使用FXML来定义预加载程序的设计吗?有趣的是,所有教程都只是通过在类外创建新实例来指导您创建预加载程序。(ProgressBar ProgressBar=新的ProgressBar();ie) 因此,让我们以下面的示例代码为例,与我一起测试: 测试预加载程序:JavaFX预加载程序问题,java,javafx,Java,Javafx,你好,亲爱的Stackoverflow 关于JavaFX类预加载程序,我有几个问题。 经过长期的研究,我还没有找到任何解决问题的正确方法,我认为这并不是我的代码的问题,而是JavaFX本身在预加载类方面的局限性 让我直截了当地谈谈我的观点:难道不能使用FXML来定义预加载程序的设计吗?有趣的是,所有教程都只是通过在类外创建新实例来指导您创建预加载程序。(ProgressBar ProgressBar=新的ProgressBar();ie) 因此,让我们以下面的示例代码为例,与我一起测试: 测试预
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
启动时的输出顺序如下:
initialize printed
BEFORE_LOAD
BEFORE_INIT
BEFORE_START
Application started!
现在,正如您所看到的,initialize()方法是第一手调用的,然后预加载程序的状态会发生变化,因此每次变化都会弹出通知——直到现在都很好
然而,困扰我的是,如果我在initialize方法中调用progressBar#setProgress,则进度实际上被设置为1,并且不会抛出任何错误。虽然这些状态发生在预加载程序初始化之后,但会出现空指针
为了理解我的意思,在handleStateNotification下取消对setProgress的注释(在BEFORE_LOAD语句下对我来说最有意义),您将看到弹出一个NullPointerException
现在,为什么会发生这种情况?如何解决此问题?这对我来说毫无意义。如果预加载程序已初始化且ProgressBar不为null,那么它如何在之后变为null?也许有一个单独使用自己类的新实例?但这对我来说没什么意义。你为什么要那样
我已经在这个问题上纠缠了几天了,我的意思是我可以制定一个时间表并“硬编码”它,但我想知道是什么导致了这些问题
TLDR;
当使用预加载程序类时,ProgressBar在初始化应用程序后将变为null,这是什么原因,我应该怎么做
编辑:
似乎该类没有在某个地方重建,idk i真的被卡住了lol当FXMLLoader加载您的FXML文件时,它会创建指定控制器的新实例。然而,这并不是理想的结果。接收状态回调的对象应该是FXML窗口的控制器 将
FXMLLoader.load(…)
块替换为
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("preloader.fxml"));
fxmlLoader.setController(this);
Parent root = fxmlLoader.load();
从FXML中删除控制器属性会导致FXMLLoader使用给定的控制器实例(即接收状态回调的实例),而不是构造指定控制器类的新实例。是否粘贴了所有FXML文件?我在里面看不到ProgressBar。@EmreDalkiran更新了它,很抱歉,是一个格式问题,与问题无关:为什么在
main
方法中使用LauncherImpl
?它是一个内部(com.sun.*
)方法。公共方法是javafx.application.application.launch
.Duh,它来自一个教程,在我运行预加载程序之前,我不想费心寻找更有效的方法。不过,谢谢你指出。编辑:我刚刚注意到,如果我按照你说的那样做,它甚至不会运行代码。对不起,我不理解其中的含义(在独立应用程序中没有真正使用预加载程序)。在Java9+中,这个方法将对您隐藏。换个角度看。
initialize printed
BEFORE_LOAD
BEFORE_INIT
BEFORE_START
Application started!
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("preloader.fxml"));
fxmlLoader.setController(this);
Parent root = fxmlLoader.load();