猿问

JavaFX 预加载器问题

你好亲爱的 Stackoverflow,


我有几个关于 JavaFX 类预加载器的问题。经过长期研究,我还没有找到任何合适的解决方案来解决我的问题,我认为这不是我的代码的真正问题,而是 JavaFX 本身在 Preloader 类方面的限制。


让我直截了当地说:难道不能使用 FXML 来定义预加载器的设计吗?有趣的是,所有教程如何仅通过从类中创建新实例来指导您创建预加载器。(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();

    }




现在,正如您所看到的, initialize() 方法被直接调用,然后预加载器的状态发生变化,因此在每次更改时都会弹出通知 - 到目前为止一切都很好。

然而让我烦恼的是,如果我在 initialize 方法中调用 progressBar#setProgress,进度实际上被设置为 1 并且不会抛出任何错误。尽管状态发生在预加载器初始化之后,但 NullPointers 发生。

要理解我的意思,请取消对 handleStateNotification 下的 setProgress 的注释(在 BEFORE_LOAD 语句下对我来说最有意义),您将看到 NullPointerException 弹出。

现在,为什么会发生?我能做些什么来解决这个问题?这对我来说没有任何意义。如果 Preloader 被初始化并且 ProgresssBar 不为 null,那么它之后如何变为 null?也许可能有一个自己的类的新实例被单独使用?但这对我来说也没有意义。你为什么会有那个?

我现在被这个问题困住了几天,我的意思是我可以去一个时间轴并“硬编码”它,但是,我想了解导致这些问题的原因。

TLDR;使用 Preloader 类初始化应用程序后,ProgressBar 变为 null,是什么原因导致的,我该怎么办?


拉莫斯之舞
浏览 208回答 1
1回答

鸿蒙传说

当 FXMLLoader 加载您的 FXML 文件时,它会创建指定控制器的新实例。然而,这并不是想要的结果。接收状态回调的对象应该是 FXML 窗口的控制器。更换你FXMLLoader.load(...)有块FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("preloader.fxml"));fxmlLoader.setController(this);Parent root = fxmlLoader.load();并从 FXML 中删除控制器属性,会导致 FXMLLoader 使用给定的控制器实例(即接收状态回调的实例),而不是构造指定控制器类的新实例。
随时随地看视频慕课网APP

相关分类

Java
我要回答