【问题标题】:FX 11: Controller loading in BaseclassFX 11:在基类中加载控制器
【发布时间】:2019-06-12 07:35:54
【问题描述】:

将 FXML 注入从基类派生的 FX 类(控制器)中有效 - 但为什么?

下面的代码实际上是有效的。但我很好奇为什么?

FXML 在抽象基类(FXMLPopup)的构造函数中加载并注入到派生类(TestfxmlController)中。

我的问题:当基类被构造(并且 fxml 被注入)时,派生类还没有被构造。 另外恕我直言,基类不应该对派生类一无所知,不是吗?

进一步说,要注入的字段在派生类中是私有的!因此加载器必须使其可访问,但基础中没有@FXML 可以允许这样做(权限仅在尚未构造的派生类中给出 - 那么该字段根本不存在在基地!)。

FXML 仍然被正确地注入到派生类中——这些字段实际上是派生类中的字段。为什么会这样?

基类:

public abstract class FXMLPopup extends Popup implements Initializable {

    @SuppressWarnings("LeakingThisInConstructor")
    public FXMLPopup(String filename) {
        super();
        final FXMLLoader loader = new FXMLLoader(FXMLLoader.class.getResource(filename));
        //if a controller is set in the fxml, ignor it.
        loader.setControllerFactory(p -> this);
        try {
            this.getContent().add(loader.load());
        } catch (IOException ex) { }
     }
}

派生类:

public class TestfxmlController extends FXMLPopup {

    @FXML
    private ChoiceBox<String> testChoiceBox;

    public TestfxmlController() {
        super("fxml/testfxml.fxml");
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        //works!!!!
        testChoiceBox.getItems().add("test");
    }
}

FXML代码:

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/11.0.1" fx:controller="TestfxmlController">
   <children>
      <ChoiceBox fx:id="testChoiceBox" layoutX="113.0" layoutY="160.0" prefWidth="150.0" />
   </children>
</AnchorPane>

我会期待什么?我希望错误超过错误。加载程序没有找到基类中的字段并且访问被拒绝.... 但它以某种方式神奇地 完美无缺。尽管我在这样一个小例子中尽可能地违反了一切。我想了解这背后的“魔力”……

【问题讨论】:

    标签: javafx javafx-8 fxml fxmlloader openjfx


    【解决方案1】:

    我想我现在明白了。派生类在基类构造函数被调用时已经被构造——只是没有被初始化。

    所以加载器实际上得到了派生类。有了给定的反射,就可以从派生类返回字段。

    这样,基类就可以初始化派生类的字段——即使基类没有任何关于其未来派生的信息。它不需要。它通过反射获取该信息(rsp. 加载程序确实如此)。

    它甚至不是粗略的,因为派生类实际上是通过反射知道的,因此知道它是正确的类型。

    所以我现在认为这个通用的 FXML Popup 代码实际上是完全有效的。

    虽然这个特定的用例是合理的,但当涉及到文档化的用例时,FXML 加载器似乎存在缺陷。

    原因:如果有人以记录的方式(不是这个用例)创建从 fxml 文件加载的控件并将其作为库分发,则该库的用户可以将其子类化。加载器现在将注入到子类中,而不是注入到它要创建的字段中,从而导致控件失败(在这种情况下,库类中的字段没有被初始化)。

    再说一遍:虽然问题中的代码似乎工作可靠,但这种行为记录在案的用例可能会导致问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多