1

I am new to JavaFX and SceneBuilder. I have been stuck for a while now on how to properly display a second view for my application directly from my controller. (If the user clicks the NEXT button, then display this fxml file) This is what I have tried so far:

package application.controller;
import java.io.IOException;

import application.Main;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class controller1 implements EventHandler<ActionEvent> {

    private Stage window;
    private AnchorPane anchorPane;
    FXMLLoader loader = new FXMLLoader();
    
    @FXML
    private Button whoami;
    @FXML
    private Button next;
    @FXML
    private Label where;
    
    @Override
    public void handle(ActionEvent event) {
        // TODO Auto-generated method stub
            
            where.setText("You're in view #1");    // When running my program, this does work
    }
    
    public void event2(ActionEvent event) throws IOException {
        // TODO Auto-generated method stub
        
            
            where.setText("NEXT was selected.");   // This second button also print to the console
            
            /* Here is where I am a little lost, 
            // after this part, my program gets an error starting with
            // Exception in thread "JavaFX Application Thread"
            // I did this approach for my start method in Main.java, and view 1 gets displayed
            // I am happy to learn from any feedback  */

            window.setTitle("View #2!!!!");
            
            loader.setLocation(Main.class.getResource("view/view2.fxml"));
            anchorPane = loader.load();
            
            Scene scene2 = new Scene(anchorPane);
            window.setScene(scene2);
            window.show();  
    }
}

This is my Main.java:

package application;

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
 
public class Main extends Application {
    private Stage window;
    private AnchorPane anchorPane;
    FXMLLoader loader = new FXMLLoader();
    
    // Sets Stage for application:
    @Override      
    public void start(Stage window) throws IOException {

        // window is what I called my primaryStage
        this.window = window;
        this.window.setTitle("View #1");
        this.window.setResizable(false);
        
        loader.setLocation(Main.class.getResource("view/view1.fxml"));
        anchorPane =loader.load();
        
        Scene scene1 = new Scene(anchorPane);
        window.setScene(scene1);
        window.show();  
    }
    
    // Main Method:
    public static void main(String[] args) {
        launch(args);
    }
    
    
}

This is the error trace:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: 

    java.lang.reflect.InvocationTargetException
        at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
        at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
        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:8411)
        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:3757)
        at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
        at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
        at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:432)
        at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:410)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
        at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
        at com.sun.glass.ui.View.notifyMouse(View.java:937)
        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(Thread.java:748)
    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:498)
        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:498)
        at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
        at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
        ... 48 more
    Caused by: java.lang.NullPointerException
        at application.controller.controller1.event2(controller1.java:48)
        ... 58 more
User_x
  • 21
  • 3

1 Answers1

-1

The window variable in your controller throws NullPointerException because it does not reference the actual window in your Main.java.

An easy workaround for this would be to create a Stage variable that you can access from your controller. Here's an example:

Main.java:

public class Main extends Application {
    private Stage window;
    private AnchorPane anchorPane;
    FXMLLoader loader = new FXMLLoader();
    protected static Stage window;

    // Sets Stage for application:
    @Override      
    public void start(Stage window1) throws IOException {
        window = window1;
        // window is what I called my primaryStage
        this.window = window;
        this.window.setTitle("View #1");
        this.window.setResizable(false);
        
        loader.setLocation(Main.class.getResource("view/view1.fxml"));
        anchorPane =loader.load();
        
        Scene scene1 = new Scene(anchorPane);
        window.setScene(scene1);
        window.show();  
    }
    
    // Main Method:
    public static void main(String[] args) {
        launch(args);
    }
}

Above here, I've created a window variable that references the window1 variable that the parameter of your start() method.

Now to make changes to the window, I can simply do so by referencing the window variable in the Main class. First remove the window declaration in your controller. Then access the window variable in your Main.java as Main.window.

public void event2(ActionEvent event) throws IOException {
        // TODO Auto-generated method stub
        
            
            where.setText("NEXT was selected."); 
             happy to learn from any feedback  */

            Main.window.setTitle("View #2!!!!");
            
            loader.setLocation(Main.class.getResource("view/view2.fxml"));
            anchorPane = loader.load();
            
            Scene scene2 = new Scene(anchorPane);
            Main.window.setScene(scene2);
            Main.window.show();  
    }
Abra
  • 19,142
  • 7
  • 29
  • 41
  • If this answer helped, please consider marking it as such. If not, feel free to let me know. – Maurice Kasomwung Nov 07 '20 at 07:04
  • no, static scope is wrong (nearly, but certainly here) always, instead pass references around as needed. Also: does this really compile? (2 fields with name window) - even if it does, it's extremely confusing – kleopatra Nov 07 '20 at 11:24
  • Hi, Thank you for the idea, Maurice, It solved my issue! to make it simpler for me; in the protected window I changed the name to window2 and changed the privacy to the public. But everything worked out as intended. :) – User_x Nov 07 '20 at 17:03