JavaFX: Exception in thread “JavaFX Application Thread” java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

前端 未结 1 2131
终归单人心
终归单人心 2020-12-20 04:40

I\'m working on JavaFX project and I\'ve an error like this:

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


        
相关标签:
1条回答
  • 2020-12-20 05:22

    You load and display DrawerContent.fxml in the initialize() method of RootLayoutController:

    public class RootLayoutController {
    
        // Reference to the main application
        @SuppressWarnings("unused")
        private MainApp mainApp;
    
        // ...
    
    
        /**
         * Initializes the controller class.
         */
        @FXML
        private void initialize() {
            try {
                VBox box = FXMLLoader.load(getClass().getResource("DrawerContent.fxml"));
                drawer.setSidePane(box);
    
                // ...
    
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Is called by the main application to give a reference back to itself
         * 
         * @param mainApp
         */
        public void setMainApp(MainApp mainApp) {
            this.mainApp = mainApp;
        }
    
    }
    

    Of course, this creates a new DrawerContentController linked to the view created from DrawerContent.fxml. At no point do you call setMainApp(...) on that controller, so in that instance of DrawerContentController, mainApp is null. Consequently, when the user presses the LOGOUT button and invokes the handler method, you get a null pointer exception.

    You need to initialize the mainApp in the DrawerContentController. You can do that with:

    import java.io.IOException;
    
    import com.jfoenix.controls.JFXDrawer;
    import com.jfoenix.controls.JFXHamburger;
    import com.jfoenix.transitions.hamburger.HamburgerBasicCloseTransition;
    
    import gn.kahere.car.manager.MainApp;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.VBox;
    
    public class RootLayoutController {
    
        // Reference to the main application
    
        // @SuppressWarnings("unused") // hmm if it's unused, I probably don't need it...
    
        // private MainApp mainApp;
    
        private DrawerContentController drawerContentController ;
    
        @FXML
        private JFXHamburger hamburger;
    
        @FXML
        private JFXDrawer drawer;
    
    
        /**
         * Controller
         */
        public RootLayoutController() {
    
        }
    
        /**
         * Initializes the controller class.
         */
        @FXML
        private void initialize() {
            try {
                FXMLLoader drawerContentLoader = new FXMLLoader(getClass().getResource("DrawerContent.fxml"));
                VBox box = drawerContentLoader.load();
                drawer.setSidePane(box);
    
                drawerContentController = drawerContentLoader.getController();
    
                HamburgerBasicCloseTransition burgerTask = new HamburgerBasicCloseTransition(hamburger);
                burgerTask.setRate(-1);
    
                hamburger.addEventHandler(MouseEvent.MOUSE_PRESSED, (e) -> {
                    burgerTask.setRate(burgerTask.getRate() * -1);
                    burgerTask.play();
    
                    if(drawer.isShown())
                        drawer.close();
                    else
                        drawer.open();
                });
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Is called by the main application to give a reference back to itself
         * 
         * @param mainApp
         */
        public void setMainApp(MainApp mainApp) {
            // this.mainApp = mainApp;
    
            // pass the main app to the drawerContentController:
            drawerContentController.setMainApp(mainApp);
        }
    
    }
    

    Obviously, you can remove all the redundant code from your MainApp class that loads FXML files and never displays their content (why would you do that anyway?):

    public class MainApp extends Application {
    
        private Stage primaryStage;
        private AnchorPane rootLayout;
    
        @Override
        public void start(Stage primaryStage) {
            this.primaryStage = primaryStage;
            this.primaryStage.setTitle("Car Manager");
    
            // Prevent the window resizing
            this.primaryStage.setResizable(false);
    
            showLogin();
        }
    
        /**
         * Show the login page
         */
        public void showLogin() {
            try {
                // Load login page
                FXMLLoader loader = new FXMLLoader();
                loader.setLocation(MainApp.class.getResource("view/Login.fxml"));
                AnchorPane login = (AnchorPane) loader.load();
    
                // Set the scene containing the login page
                Scene scene = new Scene(login);
                primaryStage.setScene(scene);
    
                // Give the controller access to the main application
                LoginController controller = loader.getController();
                controller.setMainApp(this);
    
                // Show the scene
                primaryStage.show();
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Initializes the root layout
         */
        public void initRootLayout() {
            try {
                // Load root layout
                FXMLLoader loader = new FXMLLoader();
                loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
                rootLayout = (AnchorPane) loader.load();
    
                // Give the controller access to the main application
                RootLayoutController controller = loader.getController();
                controller.setMainApp(this);
    
                // Get the DrawerContentController 
    
                // really no point in doing that since you don't display the UI you load...
                // FXMLLoader drawerLoader = new FXMLLoader();
                // drawerLoader.setLocation(MainApp.class.getResource("view/DrawerContent.fxml"));
                // drawerLoader.load(); // Load the fxml file (and do nothing with it)
                // DrawerContentController drawerController = drawerLoader.getController();
                // drawerController.setMainApp(this);
    
                // Show the scene containing the root layout
                Scene scene = new Scene(rootLayout);
                primaryStage.setScene(scene);
                primaryStage.show();
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    0 讨论(0)
提交回复
热议问题