Hello dear Stackoverflow,
I have several questions regarding the JavaFX class Preloader. After a long-term research, I haven't found any proper solution to my problem and I think it's not really the issue with my code, but rather the limits of JavaFX itself when it comes to the Preloader class.
Let me get straight up to my point: Is it not possible to use FXML to define the design of a Preloader? It's interesting to see how all the tutorials only guide you throughout creating a preloader by creating new Instances out of the classes. (ProgressBar progressBar = new ProgressBar(); ie)
So, let's take this example code for you to test this with me:
TestPreloader:
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>
TestApplication
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!");
}
}
The output if you start is in the following order:
initialize printed
BEFORE_LOAD
BEFORE_INIT
BEFORE_START
Application started!
now, as you can see the initialize() method is being called firsthand, then the state of the preloader changes and thus upon every change the notification pops up - all good until now.
Yet what bothers me is, if I call progressBar#setProgress IN the initialize method, the progress actually gets set to 1 and no errors are being thrown. Although the States occur AFTER the Preloader is initialized, NullPointers occur.
To understand what I mean, uncomment setProgress under handleStateNotification (under the BEFORE_LOAD statement would make the most sense to me), and you'll see that a NullPointerException pops up.
Now, why does it occur? What can I do to fix this issue? It just doesn't make any sense for me. If the Preloader is initialized and the ProgresssBar is not null, how can it turn null afterwards? Perhaps maybe there is a new instance of the own class being used separately? But that wouldn't make sense as well to me. Why would you have that?
I'm stuck on this problem for a few days now, I mean I could just go for a Timeline and "hardcode" it, but well, I want to learn what causes these issues.
TLDR; ProgressBar turns null after initializing the application when using the Preloader class, what causes it and what should I do?
EDIT: It seems like the class is not being reconstructed somewhere, idk i'm really stuck lol