FX 11:基类中的控制器加载

时间:2019-01-18 02:56:02

标签: javafx javafx-8 fxml fxmlloader openjfx

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

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

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

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

另外,要注入的字段在派生类中是私有的!因此,加载程序必须使其可访问,但是在基础中没有@FXML可以这样做(permision仅在尚未构造的派生类中提供-字段根本不存在在基地!)。

仍然将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");
    }
}

FXMLCode:

<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>

我期望什么?我期望错误会超过错误。加载程序未在基类中找到字段,并且访问被拒绝...。 但这 magicaly 可以正常工作。尽管我在这样一个很小的例子中违反了一切可能。我想了解这个背后的“魔力” ...

1 个答案:

答案 0 :(得分:0)

我想我现在明白了。调用基类构造函数时,已经构造了派生类-仅未初始化。

因此,加载程序实际上获取了派生类。有了给定的反射,就可以从派生类返回字段。

这样,即使基类没有任何有关其将来派生的信息,基类也可以初始化派生类的字段。不需要。它通过反射来获取该信息(加载器会这样做)。

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

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

尽管这种用例很合理,但是在记录的用例方面,FXML加载器似乎存在缺陷。

原因:如果有人创建了从fxml-文件加载的控件(采用此文档所述的方式,而不是用例说明的方式)并将其作为库分发,则该库的用户可以将其子类化。现在,加载程序将注入到子类中,而不是注入要创建的字段中,从而导致控件失败(在这种情况下,库类中的字段不会初始化)。

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