简体   繁体   中英

JavaFX FXML scene switching is not working [NullPointerException]

I'm trying to switch the layout when I press a button. I tried many things and also searched here on stackoverflow but the answers that were given seems not applicant for me.

My FrontendView.class:

/* FrontendView Class by @Aebian */
package org.aebian.umFrontend.view;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.io.IOException;


public class FrontendView extends Application {

    @FXML
    protected static Button btnLogin, btnSave, btnDiscard, btnRefresh, btnEdit;
    @FXML
    private Stage primaryStage;
    @FXML
    private Scene scene;
    @FXML
    private VBox vDefault;
    @FXML
    protected BorderPane rootLayout;

    private double xOffset = 0;
    private double yOffset = 0;

    @Override
    public void start(Stage primaryStage) {

        GridPane root = new GridPane();
        primaryStage.setMinWidth(800);
        primaryStage.initStyle(StageStyle.UNDECORATED);

        primaryStage.setMinHeight(600);
        primaryStage.setResizable(false);
        primaryStage.getIcons().add(new Image("file:res/images/uMgmt.png"));

        primaryStage.setTitle("User Management");
        Scene scene = new Scene(root, 800, 600);

        primaryStage.setScene(scene);
        this.primaryStage = primaryStage;
        root.setAlignment(Pos.CENTER);

        showRoot();
        showLogin();
    }

    public void showRoot() { // Load root layout
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(FrontendView.class.getResource("UI/umFrontendRoot.fxml"));
            rootLayout = loader.load();
            rootLayout.setId("umFrontend");

            //Let the root Layout be able to moved around.
            rootLayout.getTop().setOnMousePressed(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    xOffset = event.getSceneX();
                    yOffset = event.getSceneY();
                }
            });
            rootLayout.getTop().setOnMouseDragged(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    primaryStage.setX(event.getScreenX() - xOffset);
                    primaryStage.setY(event.getScreenY() - yOffset);
                }
            });

            // Show the scene containing the root layout.
            Scene scene = new Scene(rootLayout);
            primaryStage.setScene(scene);
            String css = FrontendView.class.getResource("UI/umFrontendStyles.css").toExternalForm();
            scene.getStylesheets().clear();
            scene.getStylesheets().add(css);

            primaryStage.show();

        } catch (IOException e) {
        }
    }

    public void showLogin() { // Load the login page.
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(FrontendView.class.getResource("UI/umFrontendLogin.fxml"));
            vDefault = loader.load();
            // Set login to center of root layout.
            rootLayout.setCenter(vDefault);
        } catch (IOException e) {
        }
    }

    public void showAbout() {  // Load the about page.
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(FrontendView.class.getResource("UI/umFrontendAbout.fxml"));
            vDefault = loader.load();

            // Set about page to center of root layout.
            this.rootLayout.setCenter(vDefault);
        } catch (IOException e) {
        }
    }

    public void showAdminOverview() {  // Load the admin overview / edit page.
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(FrontendView.class.getResource("UI/umFrontendAdminOverview.fxml"));
            VBox showAdminOverview = loader.load();
            // Set admin overview page to center of root layout.
            rootLayout.setCenter(showAdminOverview);
        } catch (IOException e) {
        }
    }

    public void showUserOverview() {  // Load the user overview / edit page.
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(FrontendView.class.getResource("UI/umFrontendUserOverview.fxml"));
            VBox showUserOverview = loader.load();
            // Set admin overview page to center of root layout.
            rootLayout.setCenter(showUserOverview);
        } catch (IOException e) {
        }
    }

    /**
     * Getter and setter.
     *
     * @return
     */
    public BorderPane getBorderPane() {
        return rootLayout;
    }

}

On Line 62 I call showLogin() that is working fine. If I try to run this via a button it will fail. Same applies for showAbout() . If I replace showLogin() on line 62 with this it will work. Over the button it won't.

My FrontendViewController.class:

package org.aebian.umFrontend.view;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.MenuItem;

import java.io.IOException;
import java.util.Optional;

public class FrontendViewController {

    FrontendView FView = new FrontendView();
    Boolean admin = false;

    @FXML
    MenuItem appClose;
    @FXML
    MenuItem appAbout;
    @FXML
    Button buttonLogin;
    @FXML
    Parent root;

    /* Button Events  */

    @FXML
    private void handleButtonAction(ActionEvent e) throws IOException {

        if (e.getSource() == appClose) { // Exit application when user clicks on Edit > Close
            System.exit(0);
        }

        else if (e.getSource() == appAbout) { // Show About page when user clicks on Help > About
            FView.showAbout();
        }

        else if (e.getSource() == buttonLogin) { // Function that gets triggered when the user presses the Login Button
            if (admin == true) {
                FView.showAdminOverview();
            } else {
                FView.showUserOverview();
            }
        }

    }

     /* Frontend Dialogs  */

    public void delUserConfirmDialog() {

        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("Delete User Dialog");
        alert.setHeaderText("Delete User $ss");
        alert.setContentText("Are you sure you want to delete the selected action?");

        Optional<ButtonType> result = alert.showAndWait();
        if (result.get() == ButtonType.OK) {
            FView.showAdminOverview();
        } else {
            // ... user chose CANCEL or closed the dialog
        }

    }
}

I also tried to set the controller dynamically but that didn't changed anything. The error I got from the compiler is this one here:

"C:\Program Files\Java\jdk1.8.0_121\bin\java" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:6660,suspend=y,server=n -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_121\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\rt.jar;C:\Users\agoebbel\Tempo Box\Development & PS\Eclipse-Workspaces\userMan\out\production\userMan;C:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.3.4\lib\idea_rt.jar" org.aebian.umFrontend.Frontend
Connected to the target VM, address: '127.0.0.1:6660', transport: 'socket'
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.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    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.control.MenuItem.fire(MenuItem.java:462)
    at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
    at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
    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.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:381)
    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$354(GlassViewEventHandler.java:417)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
    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$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)
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)
    ... 43 more
Caused by: java.lang.NullPointerException
    at org.aebian.umFrontend.view.FrontendView.showAbout(FrontendView.java:115)
    at org.aebian.umFrontend.view.FrontendViewController.handleButtonAction(FrontendViewController.java:39)
    ... 53 more

So as I can run the methods showLogin(), showAbout() and so one directly its not an error of the input stream. If you require one of my FXML files:

umFrontendAbout.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.paint.Color?>
<?import javafx.scene.text.Font?>

<VBox alignment="CENTER" prefHeight="600.0" prefWidth="900.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.aebian.umFrontend.view.FrontendView">
    <children>
        <SplitPane focusTraversable="true" orientation="VERTICAL" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
            <items>
                <AnchorPane prefHeight="576.0" prefWidth="328.0">
               <children>
                  <Label layoutX="272.0" layoutY="121.0" text="Java User Managment">
                     <font>
                        <Font size="24.0" />
                     </font>
                  </Label>
                  <Label layoutX="228.0" layoutY="164.0" text="A java written user management solution with mysql support" />
                  <Label layoutX="251.0" layoutY="181.0" text="© 2017 by Adrian (Simmarith) &amp; Alexander (Aebian)" />
                  <Label alignment="CENTER" layoutX="38.0" layoutY="14.0" minWidth="60.0" prefWidth="-1.0" style="&#10;" text="User Management \ About" textAlignment="CENTER" wrapText="false">
                     <font>
                        <Font size="18.0" fx:id="x1" />
                     </font>
                     <textFill>
                        <Color blue="0.624" green="0.624" red="0.624" fx:id="x2" />
                     </textFill>
                  </Label>
                  <Label layoutX="338.0" layoutY="220.0" text="aebian@aebian.org" />
               </children>
                </AnchorPane>
            </items>
        </SplitPane>
    </children>
</VBox>

How can I solve this?

Things I tried that are not working for me:

  • set controller dynamiclly via

( (Controller) loader.getController() ).setPrimaryStage(primaryStage);

  • created a setPrimaryStage method within the controller

Have you initialized the rootLayout before calling the method handleButtonAction()?

From what I can understand you load the rootLayout on the showRoot(), but when the app reaches the method handleButtonAction() the rootLayout it is not initialized.

Try to save the rootLayout you initialized on showRoot() so you can use it on the showAbout from handleButtonAction();

I fixed the issue myself after debugging and trying. The problem is that the Controller is not getting the initialized values. There are just present when the method start has been run. Therefore I either need to have "Application" within my controller or as JavaFX is already MVC based I just could merge my controller with the View class itself.

I did the second option and its working now. Thanks for the help.

Aebian out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM