I have a method in my Application class called getController(), which returns the controller of that stage. I am having an issue where getController() returns null if ran from an object of the Application class (note: getController() returns the correct controller if ran from the GUIHandler class).
The reason I am doing this is because the GUI code is separated from the rest of the program's code, so I require access to the controller to update specific parts of the GUI in a "Main" class.
My program is a projectile simulator program, where the user can create projectiles and see them on the screen moving around. The business logic lies within a Simulation class, while the GUI code lies within a GUIHandler class and several controllers.
The error occurs on the line "guiHandler.getController().update()" as getController() returns null, but if I run getController() from the GUIHandler's start() method it does not return null. I have included just the necessary parts of the code.
Main
public class Main
{
public Simulation currentSimulation = new Simulation();
public FileHandler fileHandler = new FileHandler();
public GUIHandler guiHandler = new GUIHandler();
public double dTime = 0;
public double dTimePerFrame = 20;
public double dSpeed = 1;
private Timer timer = new Timer();
private TimerTask task = new TimerTask()
{
/**
* This method runs every frame, updating the simulation.
*/
@Override
public void run()
{
dTime = dTime + ( dTimePerFrame / 1000 );
currentSimulation.update( dTime );
guiHandler.getController().update();
System.out.println( dTime );
}
};
GUIHandler
package simulation;
import controllers.MainController;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class GUIHandler extends Application
{
private FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource("/MainGUI.fxml") );
@Override
public void start(Stage stage) throws Exception
{
Parent root = fxmlLoader.load();
Scene scene = new Scene( root, 900, 600 );
stage.setTitle("Projectile Simulator");
stage.setScene(scene);
stage.show();
stage.setOnCloseRequest( event -> System.exit(0) );
System.out.println( getController() );
}
/**
* Gets the controller that controls the main GUI.
* @return mainController
*/
public MainController getController()
{
MainController mainController = (MainController) fxmlLoader.getController();
return mainController;
}
public static void main( String[] args )
{
launch(args);
}
}
Error
The first line is the value of getController() if run from the GUIHandler's start() method. The rest is the error that is occured if getController() is run from an object of GUIHandler. It should have returned the same thing.
controllers.MainController@65c20942
Exception in thread "Timer-0" java.lang.NullPointerException: Cannot invoke "controllers.MainController.update()" because the return value of "simulation.GUIHandler.getController()" is null
at simulation.Main$1.run(Main.java:47)
at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
at java.base/java.util.TimerThread.run(Timer.java:506)
I would like to make GUIHandler's methods static, but then I am unable to use getClass() in the FXMLLoader. I have tried making an object of the controller class, but then the FXML elements are null when I try to access them. I understand that creating an object is what is causing the issue, but I do not understand why or what else I can do to get what I want?