Tengo un problema con una pequeña app que he creado usando JavaFX, pasa que usando el loader para cargar los .fxml de la aplicación además de cargarlos obtengo instancia del controlador asociado, con el fin de poder manipular algunos detalles de la aplicación. Ha funcionado bien pero he decidido crear una pequeña ventana de carga para la app, y este no me deja obtener arrojando NullPointerException.
El problema no es obtener la excepción, está referido a la manera correcta de cargar los .fxml y controladores en JavaFX
Este error lo obtengo cargando el controlador del loadWindow.fxml, mediante el loader obteniendo la instancia de la clase LOADController mediante getController usando la clase anterior como template. La ruta del archivo es casi la misma de los fxml vecinos, y en cada .fxml existe "fx-controller:"ruta".
feb 02, 2020 5:32:48 PM javafx.fxml.FXMLLoader$ValueElement processValue
WARNING: Loading FXML document with JavaFX API of version 11.0.1 by JavaFX runtime of version 8.0.231
java.lang.NullPointerException
at application.RuntimeCommand.initializeView(RuntimeCommand.java:57)
at application.RuntimeCommand.init(RuntimeCommand.java:36)
at application.Main.start(Main.java:12)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:186)
at java.lang.Thread.run(Unknown Source)
En la clase a continuación, se cargan los fxml al inicio de la aplicación, y dentro del método loadStage se carga el controlador de cada uno, repito los otros dos controladores cargan perfectamente pero este se ha resistido.
Clase general donde cargo los .fxml
package application;
import java.io.IOException;
import java.util.ArrayList;
import controller.CRUDController;
import controller.GUIController;
import controller.LOADController;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import model.Clock;
import model.TableMovement;
import model.XMLGenerator;
public class RuntimeCommand {
public static Stage mainWindow, crudWindow, loadWindow;
public static Clock clock;
public static CRUDController controllerCRUD;
public static GUIController controllerGUI;
public static LOADController controllerLOAD;
public static ArrayList<TableMovement> dataList = new ArrayList<TableMovement>();
public static final int GUI = 0, CRUD = 1, LOAD = 2;
public static void init() {
initializeLoadWindow();
initializeView();
loadXMLFile();
initializeClock();
mainWindow.centerOnScreen();
controllerLOAD.reset();
loadWindow.hide();
mainWindow.showAndWait();
}
private static void initializeLoadWindow() {
loadWindow = loadStage("../view/LoadWindow.fxml", LOAD);
loadWindow.setResizable(false);
loadWindow.centerOnScreen();
loadWindow.initStyle(StageStyle.UNDECORATED);
loadWindow.show();
}
private static void initializeView() {
controllerLOAD.reset();
loadWindow.show();
mainWindow = loadStage("../view/Application.fxml", GUI);
crudWindow = loadStage("../view/crudWindow.fxml", CRUD);
crudWindow.setResizable(false);
mainWindow.setResizable(false);
mainWindow.setTitle("ChaosLogger by jrv99");
// close actions
mainWindow.setOnCloseRequest( (e)-> {
loadWindow.show();
controllerLOAD.lblText.setText("Saving data");
XMLGenerator.generateXMLFromList(controllerGUI.getMovementList());
controllerLOAD.lblText.setText("Closing");
loadWindow.hide();
Platform.exit();
System.exit(0);
});
crudWindow.setOnCloseRequest((e) -> {
crudWindow.hide();
});
controllerLOAD.lblText.setText("Loading movements");
// load the data getted from the xml file
controllerGUI.loadList();
}
public static Stage loadStage(String path, int mode) {
Stage stage = null;
BorderPane root;
Scene scene;
try {
FXMLLoader loader = new FXMLLoader(RuntimeCommand.class.getResource(path));
switch(mode) {
case GUI:
controllerGUI = loader.<GUIController>getController();
break;
case CRUD:
controllerCRUD = loader.<CRUDController>getController();
break;
case LOAD:
controllerLOAD = loader.<LOADController>getController();
break;
default: {
System.out.println("Modo de controlador no encontrado");
root = null;
}
}
root = (BorderPane) loader.load();
stage = new Stage();
scene = new Scene(root);
scene.getStylesheets().add(RuntimeCommand.class.getResource("../view/application.css").toExternalForm());
stage.setScene(scene);
stage.getIcons().add(new Image("file:res/appIcon.png"));
} catch (IOException e) {
e.printStackTrace();
}
return stage;
}
private static void initializeClock() {
controllerLOAD.lblText.setText("Loading time");
clock = Clock.getInstance();
clock.start();
}
private static void loadXMLFile() {
controllerLOAD.lblText.setText(controllerLOAD.defaultText+"data");
loadWindow.show();
XMLGenerator.loadXMLtoList(dataList);
//loadWindow.hide();
controllerLOAD.reset();
}
}
Controlador de la ventana de carga
package controller;
import java.net.URL;
import java.util.ResourceBundle;
import com.jfoenix.controls.JFXProgressBar;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class LOADController implements Initializable {
public static final String defaultText = "Loading ";
@FXML public Label lblText;
@FXML public JFXProgressBar pbLoad;
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
reset();
}
public void reset() {
lblText.setText(defaultText);
pbLoad.getAccessibleText();
}
}
FXML asociado
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXProgressBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.text.Font?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="98.0" prefWidth="396.0" style="-fx-background-color: #000000;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.LOADController">
<center>
<BorderPane prefHeight="73.0" prefWidth="396.0" BorderPane.alignment="CENTER">
<bottom>
<Label fx:id="lblText" alignment="CENTER" contentDisplay="CENTER" prefHeight="87.0" prefWidth="396.0" style="-fx-text-fill: #ffffff;" text="Cargando ..." BorderPane.alignment="CENTER">
<font>
<Font name="Corbel Light" size="25.0" />
</font>
</Label>
</bottom>
</BorderPane>
</center>
<bottom>
<JFXProgressBar fx:id="pbLoad" prefHeight="13.0" prefWidth="405.0" style="-fx-background-color: #909090;" BorderPane.alignment="CENTER" />
</bottom>
</BorderPane>
Clase principal package application;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
RuntimeCommand.init();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Tomar en cuenta que uso una estructura de paquetes: dentro del
->src
-> app
-> controller
-> model
-> view
Uso JavaFX API of version 11.0.1 by JavaFX runtime of version 8.0.231, hasta el momento los demas controladores de la aplicacion funcionan segun lo esperado, pero este ha sido la excepción. Trabajo en Eclipse 2019-12 (4.14.0)