我有一个名为MainStage的类,它扩展到javafx的stage类。这是类的一部分。
public void changeScene(){
if(onLogin)
setScene(mainScene);
else{
setScene(loginScene);
onLogin = false;
}
}
我在MainStage类中使用这个方法来改变场景。我调用场景控制器内部的MainStage
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)
MainStage stage
行需要移动到事件处理程序中。
目前,它是一个不在任何方法中的声明,因此它被认为是类的一个字段。这意味着它在loginSceneController实例创建之前运行,并可供其他代码使用。由于没有其他代码可以看到该对象,所以所有其他字段(包括submit)仍然为空。
此外,如果按钮还没有添加到场景中,你就不能很好地访问按钮的场景。可以安全地假设,如果用户设法触发提交按钮的动作,按钮必须在一个可见窗口的场景中,所以事件处理程序是访问父场景和窗口的理想场所。
既然你问了执行顺序:任何时候用new
创建一个对象,该对象必须首先运行它的所有初始化器,按照它们在代码中出现的顺序,然后运行被调用的构造函数。在此之前,对象实际上并没有创建,其他代码也不能使用它或引用它,*包括FXMLLoader。所有字段初始值为null、0或false,除非它们被初始化(如private int x = 4;
)。
在您的对象完全构造之前,没有一个@FXML
注释字段是非空的。
*从技术上讲,构造函数有可能在构造函数完成之前"泄漏"对新对象的引用,但这样做被认为是不好的做法。