【问题标题】:JavaFX init() method resetting field to nullJavaFX init() 方法将字段重置为 null
【发布时间】:2016-01-04 13:43:37
【问题描述】:

我正在 JavaFX 中创建一个小程序,并且有一个需要分配 EventHandler 的按钮。我在我的视图(扩展应用程序的类)的 init() 方法中创建并分配了这个按钮。

Button ok = new Button("   OK   ");
ok.setOnAction(this.eventHandler);

理想情况下,我想在构造 View 对象时传递这个 eventHandler,但是我在这样做时遇到了一些困难,所以我决定只使用一个简单的 setter。

public void setEventHandler(EventHandler<ActionEvent> eventHandler) {
 this.eventHandler = eventHandler;
}

为了开始一切,我在 Controller 类的 main 方法中运行了几行代码:

View v = new View();
v.setEventHandler(new HandleOk(v));
javafx.application.Application.launch(View.class);

其中 HandleOk 是 EventHandler。它需要对我的视图类的引用,以便它可以查询其某些字段的状态,因此是用视图构造的。运行此代码并单击 JavaFX 按钮会导致空指针异常。

然后我设置了三个System.out.format("Event handler is null: %b\n", v.eventHandler == null);,一个在我的 Controller 的 main 方法中,一个在我的 View 的 init() 方法(从 JavaFX 应用程序继承的方法)的顶部,以及在按钮的 setOnAction 方法中。因此如下:

public class Controller {
  //~~ other stuff ~~
  public static void main(String[] args) {
    View v = new View();
    v.setEventHandler(new HandleOk(v));
    System.out.format("Event handler is null: %b\n", v.eventHandler == null);
    javafx.application.Application.launch(View.class);
  }
 //~~ other stuff ~~
}

public class View extends Application {
  EventHandler<ActionEvent> eventHandler;

  public void setEventHandler(EventHandler<ActionEvent> eventHandler) {
    System.out.println("Event Handler set");
    this.eventHandler = eventHandler;
  }

  @Override
  public void init() {
    System.out.format("Event Handler in init() is null: %b\n", eventHandler == null);
  //  ~~ other stuff ~~
    Button ok = new Button("   OK   ");
    ok.setOnAction((ActionEvent) -> {
      System.out.format("Event Handler in button is null: %b", this.eventHandler == null));
      if (!(this.eventHandler == null) {
        this.eventHandler.handle(ActionEvent);
      }
    });
 //   ~~ other stuff ~~
  }

运行它并单击我的 javaFX 应用程序中的按钮会导致将以下内容打印到控制台:

Event Handler set
Event Handler is null: false
Event Handler in init() is null: true
Event Handler in button is null: true

有趣的是,将以下行添加到我的 init() 方法中删除了空指针异常并且我的应用程序可以正常工作。

public void init() {
  eventHandler = new Controller.HandleOk(this);
 // ~~  other stuff ~~
}

理想情况下,我希望我的控制器将 HandleOk 传递给我的视图,而不是我的视图必须从我的控制器中获取 HandleOk。我只能得出结论,当 JavaFX 加载扩展应用程序的类时,它会重置已初始化的任何字段,从而导致您只能在 init() 方法中初始化字段的情况。如何从外部源将 HandleOk 传递给视图?

【问题讨论】:

  • 不是“javafx.application.Application.launch(View.class);”创建自己的视图实例?这意味着您在此之前所做的任何事情都将毫无意义,因为正在显示的实例不是您创建的实例
  • 文档确认了您的答案,所以现在我知道为什么该字段似乎被重置了。 Launch 是一个 void 方法,不会返回对实例的引用,所以我仍然不知道如何从外部传入 HandleOk。

标签: java javafx


【解决方案1】:

Application.launch(View.class)

正在创建一个新的 View 实例,默认情况下它对事件处理程序具有 null 值,并且与您自己创建的 View 类不同。此外,如果您注意到 View 类的 init() 方法仅被调用一次。这是由 Application.launch 方法调用的。

我建议将视图和应用程序逻辑拆分为不同的类。 IE。不要从 Application 扩展视图,创建另一个扩展 Application 的 MainApp 类。

【讨论】:

  • 您能详细说明拆分视图和应用程序逻辑吗?我的想法是我的视图有一个按钮,单击该按钮会向我的控制器发送消息。从那里我的控制器与我的模型交谈以完成这项工作。拆分我的视图和应用程序后,此流程看起来有何不同?
  • 基本上我的控制器应该是扩展应用程序的类,因为它是我程序的入口点。明白了。
【解决方案2】:

您是否设置该字段?

public void setEventHandler(EventHandler<ActionEvent> eventHandler) {
    System.out.println("Event Handler set");
    this.eventHandler = eventHandler; // missing?   
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-24
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 2018-06-14
    • 1970-01-01
    • 2011-05-25
    相关资源
    最近更新 更多