【问题标题】:Making stages a separate class and making unique methods for them使阶段成为一个单独的类并为它们制作独特的方法
【发布时间】:2016-06-27 16:43:05
【问题描述】:

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

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)仍然为空。
  • VGR 的评论回答了这个问题。你能解释一下java运行程序的顺序吗?
  • 此外,即使您将分配移至 initialize 方法,也不会设置场景,因为显然您需要在将 fxml 添加到场景之前加载它。只需在EventHandler 中登台即可。这些操作并不昂贵......

标签: java user-interface javafx


【解决方案1】:

MainStage stage 行需要移动到您的事件处理程序中。

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

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

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

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


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

【讨论】:

    猜你喜欢
    • 2020-11-27
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 1970-01-01
    相关资源
    最近更新 更多