Javafx - 应用程序类可以是控制器类 [英] Javafx - Can application class be the controller class

查看:95
本文介绍了Javafx - 应用程序类可以是控制器类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在自学JavaFX,我已经采用了一个简单的示例程序,该程序硬编码视图并将其转换为使用FXML的程序(主要是因为我可以使用SceneBuilder构建UI)。我没有编写单独的控制器类,而是使用应用程序类(因此有1个Java文件和1个FXML文件)。我没有使用 initialize()方法,因为它是一个线性流(显示UI,填充字段,等待输入)。视图弹出,但随后应用程序出错,因为没有控件被映射到适当的变量(因此对于 @FXML TableView< ...> table table null )。

I'm currently teaching myself JavaFX, and I've taken a simple example program that's hardcoded the view and am turning it into one that uses FXML (mostly so I can use SceneBuilder for building UIs). Rather than writing a separate controller class, I'm using the application class (so there's 1 Java file and 1 FXML file). I'm not using an initialize() method as it's a linear flow (display the UI, populate the fields, wait for input). The view pops up, but then the app errors out as none of the controls are mapped to the appropriate variables (so for @FXML TableView<...> table, table is null).

但是,我放入了用于调试的 initialize()方法,在 initialize()中注入控件,然后在返回null时返回 initialize()退出。

However, I put in an initialize() method for debugging, the controls are injected while in initialize(), and then return to null when initialize() exits.

所以问题是,JavaFX是否将应用程序类的新实例实例化为单独的控制器类?这可以解释为什么变量超出范围。或者它是别的东西(例如,只有在从JavaFX动作回调时才注入控件)?

So the question is, does JavaFX instantiate a new instance of the application class as a separate controller class? This would explain why the variable are going out of scope. Or is it something else (e.g. the controls are injected only when being called back from JavaFX actions)?

推荐答案

默认行为 FXMLLoader 是创建控制器类的新实例并将该实例用作控制器。

The default behavior of the FXMLLoader is to create a new instance of the controller class and use that instance as the controller.

具体来说, FXMLLoader 执行如下操作:

Specifically, the FXMLLoader does something like:


  • 读取根FXML元素。


    • 如果根FXML元素具有 fx:controller 属性,则


      • 如果控制器已存在,则抛出异常,否则创建指定类 1 的实例并将其设置为控制器

      • Read the root FXML element.
        • If the root FXML element has a fx:controller attribute, then
          • If a controller already exists, throw an exception, otherwise create an instance of the specified class1 and set that as the controller

          所以,你问的问题是:


          应用程序类可以是控制器类

          Can application class be the controller class

          是的,但这可能是一个糟糕的主意。如果只是使用 fx:controller Application 子类指定为控制器类,那么<$的第二个实例c $ c>应用程序创建子类, @FXML - 在第二个实例上注入注释字段,初始化()在第二个实例上调用方法。显然, @FXML -fields永远不会在调用 start(...)的实例上初始化,并且永远不会在该实例上调用 initialize()方法。

          Yes, but it's probably a terrible idea. If you simply specify the Application subclass as the controller class using fx:controller, then a second instance of the Application subclass is created, @FXML-annotated fields are injected on that second instance, and the initialize() method is invoked on that second instance. Obviously, the @FXML-fields are never initialized on the instance on which start(...) is invoked, and the initialize() method is never invoked on that instance.

          您可能想要的问题是:


          启动时创建的应用程序类实例是否可以用作控制器?

          Can the application class instance created at launch be used as the controller?

          这个问题的答案也是肯定的,除了你打算立即丢弃的非常小的演示程序之外,它也可能是个坏主意。你可以这样做

          The answer to this is also yes, and, aside from very small demo programs you intend to immediately discard, it's also probably a very bad idea. You would do this by

          public class MyApp extends Application {
          
              @FXML
              private Node someNode ;
          
              public void initialize() {
                  // do something with someNode 
              }
          
              @Override
              public void start(Stage primaryStage) throws Exception {
                  FXMLLoader loader = new FXMLLoader(getClass().getResource("/path/to/fxml/file.fxml"));
                  loader.setController(this);
                  Parent root = loader.load();
                  primaryStage.setScene(new Scene(root));
                  primaryStage.show();
              }
          }
          

          请注意,要使用此代码,您的FXML文件一定不能拥有 fx:controller 属性。

          Note that to use this code, your FXML file must not have a fx:controller attribute.

          这个问题就是你没有分离,没有灵活性。 (例如,如果您在某处创建了FXML文件中定义的视图的第二个实例,则最终会得到第二个 Application 子类实例,这最好是违反直觉的(一个应用程序两个应用程序实例...)。)

          The problem with this is that you have no separation and no flexibility. (E.g. if you create a second instance of the view defined in your FXML file somewhere, you end up with a second Application subclass instance, which is at best counterintuitive (one application with two Application instances...).)

          所以我主张基本上为控制器使用一个类每个案例。 应用程序子类应包含最少的代码,并且只应用于启动应用程序。

          So I would advocate using a separate class for the controller in basically every case. The Application subclass should contain minimal code and should be used only for starting the application.

          1 这一步实际上有点复杂。如果在 fx:controller 属性中指定了类,并且没有控制器已存在, FXMLLoader 将检查< a href =http://docs.oracle.com/javase/8/javafx/api/javafx/fxml/FXMLLoader.html#setControllerFactory-javafx.util.Callback-\"rel =noreferrer> 的ControllerFactory 。如果存在,则将控制器设置为将指定的 Class 传递给 controllerFactory call()方法,否则通过在指定的类上调用 newInstance()来创建它(有效地调用它的无参数构造函数) )。

          1 This step is actually a little more complex. If a class is specified in the fx:controller attribute, and no controller already exists, the FXMLLoader checks for a controllerFactory. If one exists, then the controller is set as the result of passing the specified Class to the controllerFactory's call() method, otherwise it is created by calling newInstance() on the specified class (effectively calling its no-argument constructor).

          这篇关于Javafx - 应用程序类可以是控制器类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆