I'm getting an java.lang.reflect.InvocationTargetException exception in JavaFX app and I have no idea how to fix it

huangapple go评论82阅读模式
英文:

I'm getting an java.lang.reflect.InvocationTargetException exception in JavaFX app and I have no idea how to fix it

问题

我正在构建一个小的D&D(龙与地下城)项目,但在使用JavaFX时遇到了一些问题。我试图在保持同一舞台的情况下切换多个场景。我正在使用MVC设计,并且每当调用控制器时都会传递primaryStage。然而,当我试图从我的UI类调用并从控制器获取舞台时,它会抛出InvocationTargetException。

主类:

package dnd;

import javafx.application.Application;
import javafx.stage.Stage;

public class DnD extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception { 
        primaryStage.setTitle("Dungeons and Dragons");
        StartMenuCtrl startMenuCtrl = new StartMenuCtrl(primaryStage);
        primaryStage.show();        
    }

    public static void main(String[] args) {
        launch(args);
    }   
}

开始菜单控制器类:

package dnd;

import javafx.stage.Stage;

public class StartMenuCtrl {
    private final StartMenuUI startMenuUI;
    private final Stage primaryStage;

    public StartMenuCtrl(Stage primaryStage) {
        this.startMenuUI = new StartMenuUI(this);
        this.primaryStage = primaryStage;        
    }
    
    public void newButtonIsPressed() {
        System.out.println("New Button is pressed");
    }
    
    public void createButtonIsPressed() {
        System.out.println("Create Button is pressed");
        CreateCharCtrl createCharCtrl = new CreateCharCtrl(primaryStage);
    }
    
    public void loadButtonIsPressed() {
        System.out.println("Load Button is pressed");
    }
    
    public void joinButtonIsPressed() {
        System.out.println("Join Button is pressed");
    }
    
    public Stage getStage() {
        return this.primaryStage;
    }
}

开始菜单UI类:

package dnd;

import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class StartMenuUI {
    private final StartMenuCtrl startMenuCtrl;
    private final Text title;
    private final Button newBtn;
    private final Button createBtn;
    private final Button loadBtn;
    private final Button joinBtn;

    public StartMenuUI(StartMenuCtrl startMenuCtrl) {
        this.startMenuCtrl = startMenuCtrl;
        this.title = new Text();
        this.newBtn = new Button("New Game");
        this.createBtn = new Button("Create Character");
        this.loadBtn = new Button("Load Saved Game");
        this.joinBtn = new Button("Join Game");
        initComponents();
    }
    
    private void initComponents() {
        Group root = new Group(title, newBtn, createBtn, loadBtn, joinBtn);
        Scene scene = new Scene(root, 1280, 720);
        Stage stage = startMenuCtrl.getStage();
        stage.setScene(scene);
    }
}

错误信息:

Exception in Application start method
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	...

Caused by: java.lang.RuntimeException: Exception in Application start method
	at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
	...

Caused by: java.lang.NullPointerException
	at dnd.StartMenuUI.initComponents(StartMenuUI.java:70)
	...

希望能对您有所帮助!由于项目刚刚开始,如果需要进行重大更改,也欢迎提出。

英文:

I'm building a small D&D side project, but having trouble navigating my way through JavaFX. I'm attempting to move through several scenes while remaining on the same stage. I'm using an MVC design and passing though the primaryStage whenever the controller is called. However, when I try to call from my UI class and get the stage from my controller, it throws a InvocationTargetException.

Main Class:

package dnd;

import javafx.application.Application;
import javafx.stage.Stage;

public class DnD extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception { 
        primaryStage.setTitle("Dungeons and Dragons");
        StartMenuCtrl startMenuCtrl = new StartMenuCtrl(primaryStage);
        primaryStage.show();        
    }

    public static void main(String[] args) {
        launch(args);
    }   
}

Start Menu Controller Class:

package dnd;

import javafx.stage.Stage;

public class StartMenuCtrl {
    private final StartMenuUI startMenuUI;
    private final Stage primaryStage;

    public StartMenuCtrl(Stage primaryStage) {
        this.startMenuUI = new StartMenuUI(this);
        this.primaryStage = new Stage();        
    }
    
    public void newButtonIsPressed() {
        System.out.println("New Button is pressed");
    }
    
    public void createButtonIsPressed() {
        System.out.println("Create Button is pressed");
        CreateCharCtrl createCharCtrl = new CreateCharCtrl(primaryStage);
    }
    
    public void loadButtonIsPressed() {
        System.out.println("Load Button is pressed");
    }
    
    public void joinButtonIsPressed() {
        System.out.println("Join Button is pressed");
    }
    
    public Stage getStage() {
        return this.primaryStage;
    }
}

Start Menu UI Class:

package dnd;

import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class StartMenuUI {
    private final StartMenuCtrl startMenuCtrl;
    private final Text title;
    private final Button newBtn;
    private final Button createBtn;
    private final Button loadBtn;
    private final Button joinBtn;

    public StartMenuUI(StartMenuCtrl startMenuCtrl) {
        this.startMenuCtrl = startMenuCtrl;
        this.title = new Text();
        this.newBtn = new Button("New Game");
        this.createBtn = new Button("Create Character");
        this.loadBtn = new Button("Load Saved Game");
        this.joinBtn = new Button("Join Game");
        initComponents();
    }
    
    private void initComponents() {
        Group root = new Group(title, newBtn, createBtn, loadBtn, joinBtn);
        Scene scene = new Scene(root, 1280, 720);
        Stage stage = startMenuCtrl.getStage();
        stage.setScene(scene);
    }
}

Error:

Exception in Application start method
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 com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
	at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
	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.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
	at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
	at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
	at dnd.StartMenuUI.initComponents(StartMenuUI.java:70)
	at dnd.StartMenuUI.<init>(StartMenuUI.java:25)
	at dnd.StartMenuCtrl.<init>(StartMenuCtrl.java:10)
	at dnd.DnD.start(DnD.java:11)
	at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
	at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
	at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
	at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
	at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
	... 1 more

Any help would be appreciated! I'm very early in the project so drastic change tips would be appreciated as well I'm getting an java.lang.reflect.InvocationTargetException exception in JavaFX app and I have no idea how to fix it

答案1

得分: 5

你遇到了一个初始化顺序问题。在你的 StartMenuCtrl 构造函数中,你将对 this 的引用传递给了 StartMenuUI 构造函数。然后 StartMenuUi 构造函数调用 initComponents,而 initComponents 又调用了 startMenuCtrl.getStage()... 但是那个方法返回了 null,因为 StartMenuCtrl 构造函数尚未执行完成,还没有初始化它的 primaryStage 字段。

尝试重新调整 StartMenuCtrl 构造函数中的行,使它们按照以下顺序排列:

this.primaryStage = new Stage(); // 这个需要首先发生!
this.startMenuUI = new StartMenuUI(this);

这个问题说明了为什么通常来说,在对象构造过程中最好不要让 this 引用逸出,具体可以参考这里的说明

英文:

You've got an initialization order issue. In your StartMenuCtrl constructor, you're passing a reference to this to the StartMenuUI constructor. The StartMenuUi constructor then calls initComponents, which calls startMenuCtrl.getStage()... but that method returns null because the StartMenuCtrl constructor has not finished executing, and has not yet initialized its primaryStage field.

Try reordering the lines in the StartMenuCtrl constructor so they're in this order:

this.primaryStage = new Stage(); // this needs to happen first!
this.startMenuUI = new StartMenuUI(this);

This problem illustrates why, generally speaking, it's best not to let the this reference escape during object construction.

huangapple
  • 本文由 发表于 2020年10月28日 04:42:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/64562606.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定