MY SOLUTION
In the end the problem relied on the fact that I instantiated in the initialization method an ImageView that only existed on principal.fxml, and so, whenever I started a new scene, the controller looked for that ImageView, thus giving a NullPointerException. I just removed that initialization for the image and added it through the fxml. I don't know if this is the best way to do it, but it worked well for me.
I have a JavaFX application that has the following classes and FXML files:
- Main.java that extends Application and has the start method
- Controller.java that controls all my FXML files, and from where I want to open dynamically the scenes
- principal.fxml
- test.fxml
- final.fxml
My application starts with principal.fxml. I want to open my test.fxml scene after the user clicks on a button on the principal scene, after getting an XML file for later processing. And finally, in the test scene, again when the user clicks on a button, I want to open the final.fxml scene.
My project structure is the following:
├── res
│ ├── css
│ │ └── estils.css
│ ├── imatges
│ │ └── logoFinal.png
│ ├── view
│ │ ├── final.fxml
│ │ ├── principal.fxml
│ │ └── test.fxml
│ └── xml
│ └── testAngles.xml
├── SERRANO_PEJO_M03UF5.iml
└── src
└── jtest
├── Controlador.java
└── Main.java
My Main.java code is the following:
package jtest;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/principal.fxml"));
Parent root = loader.load();
/*Controlador controlador = (Controlador)loader.getController();
controlador.setStageAnd*/
primaryStage.setTitle("jTest");
Scene escena = new Scene(root, 640, 400);
escena.getStylesheets().add(this.getClass().getResource("/css/estils.css").toExternalForm());
primaryStage.setScene(escena);
primaryStage.setResizable(false);
primaryStage.centerOnScreen();
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
And my Action method (in Controller.java) to open the new scene is the following:
@FXML
public void carregaTestAction (ActionEvent event) {
// Mostra un diàleg amb la selecció de l'arxiu
FileChooser seleccioArxiu = new FileChooser();
seleccioArxiu.setTitle("Selecciona l'arxiu de test");
arxiuTest = seleccioArxiu.showOpenDialog(btCarrega.getScene().getWindow());
// Carrega el nou stage, TEST
stage = (Stage) btCarrega.getScene().getWindow();
Parent root;
try {
root = FXMLLoader.load(getClass().getResource("/view/test.fxml"));
Scene sceneTest = new Scene(root, 640, 400);
stage.setScene(sceneTest);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
And this is my error stacktrace:
Stacktrace:
javafx.fxml.LoadException:
/home/biel/Documents/M03UF5/SERRANO_PEJO_M03UF5/out/production/SERRANO_PEJO_M03UF5/view/test.fxml
at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3237)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
at jtest.Controlador.carregaTestAction(Controlador.java:148)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:273)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1782)
at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8879)
at javafx.controls/javafx.scene.control.Button.fire(Button.java:200)
at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3851)
at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1200(Scene.java:3579)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1849)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2588)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:390)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.NullPointerException
at jtest.Controlador.initialize(Controlador.java:95)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2573)
... 66 more
I also tried only with this code (which gave us our teacher), but it gave me an error too:
@FXML
public void carregaTestAction (ActionEvent event) {
// Mostra un diàleg amb la selecció de l'arxiu
FileChooser seleccioArxiu = new FileChooser();
seleccioArxiu.setTitle("Selecciona l'arxiu de test");
arxiuTest = seleccioArxiu.showOpenDialog(btCarrega.getScene().getWindow());
// Carrega el nou stage, TEST
stage = (Stage) btCarrega.getScene().getWindow();
Parent root;
try {
root = FXMLLoader.load(getClass().getResource("/view/test.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
}
I searched and found Javafx: Open a new FXML from another Java Class, "FXMLLoader.constructLoadException" when trying to run java fx application and JavaFX open a new scene, but I still can't understand how this should work and why is it giving me this error.
EDIT: I know what a NullPointerException is, but I don't understand how, even with the code I have, I can't open a new scene. I thought it might be because it didn't get my test.fxml file the right way, but it IS getting my principal.fxml file without any issues in my main class, and an image file in my Controller class.
EDIT 2 (2019-03-22 00:31): I revised my Stacktrace and now I understand why you addressed me to the NullPointer question. In my initialize method in my Controller class, I get an image, only for my principal.fxml scene:
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
// PRINCIPAL.FXML
// Insereix la imatge del logo
Image imatgeLogo = new Image(this.getClass().getResourceAsStream("/imatges/logoFinal.png"));
ivLogo.setImage(imatgeLogo);
}
What I understand from this exception is that when I try to initialize the other stages, the controller doesn't find an ImageView to get? If this is it, how can I make the controller get the image ONLY when it is starting my principal.fxml scene? Thank you and sorry for any inconvenience and misunderstanding.