I want my code to work such that when I click on a Button, a new scene opens, but it doesn't work and I don't know why.
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
Parent root = FXMLLoader.load(getClass().getResource("FXML/LoginScene.fxml"));
scene = new Scene(root,400,400);
openScene = new OpenScene(writer);
window.setScene(scene);
window.show();
}
public static void main(String[] args){
launch(args);
}
@FXML protected void btnConnect(ActionEvent event) {
System.out.println("hallo");
try {
openScene.start(window);
} catch (Exception e) {
e.printStackTrace();
}
}
The GUI successfully shows up, but when I press the Button, it throws an Exception.
public class OpenScene extends Application{
PrintWriter writer;
@Override
public void start(Stage window) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXML/OpenScene.fxml"));
Scene scene = new Scene(root, 200 ,200);
window.setScene(scene);
window.show();
}
public OpenScene(PrintWriter writer){
this.writer = writer;
}
}
Update
I tried to separate the application class from the controller class as in James_D's answer below, but I got the following exception:
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1762)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1645)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8216)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3724)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3452)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1728)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2461)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:348)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:273)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:382)
at com.sun.glass.ui.View.handleMouseEvent(View.java:553)
at com.sun.glass.ui.View.notifyMouse(View.java:925)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1759)
... 43 more
Caused by: java.lang.NullPointerException
at MainController.btnConnect(MainController.java:22)
... 53 more
It looks like you are trying to use your main application class as the controller class. This is going to be confusing, and you should avoid it. Here is what happens:
When you start up the application, it calls
launch(...)
. Thelaunch
method, inherited fromApplication
, will do a bunch of important "housekeeping", such as starting the JavaFX toolkit and the JavaFX Application Thread. It then creates an instance of your application subclass, creates an initialStage
and calls thestart(...)
in that instance.In your
start(...)
method, you initialized a couple of instance variables (window
andopenScene
), and loaded an FXML file, displaying its contents. TheFXMLLoader.load(...)
method does the following:fx:controller
attribute in the FXML file@FXML
-annotated fields into the controller instanceNotice that if you specify the same class for the application and for the controller, two instances of that class will be created. One is created by the
launch
method, and one is created by theFXMLLoader
. Note that only the instance created by thelaunch
method has had thestart(...)
method invoked. Since you initialize the instance variables in thestart(...)
method, those variables are not initialized in the instance created by theFXMLLoader
. So in the instance created by theFXMLLoader
(the "controller instance", if you like),window
andopenScene
are not initialized. Hence the linewill throw a
NullPointerException
.Since the application and controller really have completely different roles, you should separate them into different classes. This will make things far less confusing. Note that you can always find the window in which a node is displayed by calling
so there is no need to cache the
Stage
instance.So:
and use a different class for the controller:
Note also that there is no need for your
OpenScene
class to be anApplication
subclass: you only need one such class per application: