使阶段成为一个单独的类,并为它们制作独特的方法

时间:2016-06-27 16:43:06

标签: java user-interface javafx

我有一个名为MainStage的类,它扩展到javafx的stage类。 这是该课程的一部分。

public void changeScene(){

    if(onLogin)
      setScene(mainScene);
    else{
    setScene(loginScene);
    onLogin = false;
 }
}

我在MainStage类中使用此方法来更改场景。我将控件内的MainStage称为Scene

public class loginSceneController{

@FXML
private Button submit;
@FXML
private TextField usernameField;
@FXML
private PasswordField passwordField;

MainStage stage = (MainStage) submit.getScene().getWindow(); //This is where the nullpointer is thrown


public void handle() {
    submit.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            stage.changeScene();
            System.out.println("Stage changed sucessfully!!");
        }
    });

 }

}

当我尝试运行它时,它会抛出这个:

Exception in thread "main" 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$155(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: /C:/Users/Max/workspace/CloudCCP/target/classes/Window/LoginScene.fxml:9
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
at Window.MainStage.<init>(MainStage.java:24)
at Window.Window.start(Window.java:28)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(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$148(WinApplication.java:191)
... 1 more
Caused by: java.lang.NullPointerException
at Window.loginSceneController.<init>(loginSceneController.java:30)

1 个答案:

答案 0 :(得分:1)

需要在事件处理程序中移动MainStage stage行。

目前,它是一个不在任何方法中的声明,因此它被认为是该类的一个字段。这意味着它在创建loginSceneController实例之前运行,并且可供其他代码使用。由于没有其他代码可以看到该对象,所有其他字段(包括提交)仍为空。

此外,如果尚未将按钮添加到场景中,则无法很好地访问按钮的场景。可以安全地假设,如果用户设法触发提交按钮的操作,则该按钮必须位于可见窗口的场景中,因此事件处理程序是访问父场景和窗口的理想位置。

由于您询问了执行顺序:每次使用new创建对象时,对象必须首先按照它们在代码中出现的顺序运行所有初始化程序,然后运行调用的构造函数。在此之前,实际上并没有创建对象,也没有其他代码可以使用它或引用它, * 包括FXMLLoader。所有字段最初都为null,零或false,除非它们已初始化(如private int x = 4;)。

在完全构造对象之前,@FXML - 注释字段都不是非空的。

*从技术上讲,构造函数可能在构造函数完成之前“泄漏”对新对象的引用,但这被认为是不好的做法。