【问题标题】:How to access components from different file controller?如何从不同的文件控制器访问组件?
【发布时间】:2017-05-25 12:35:00
【问题描述】:

假设我有两个 FXML 文件:主文件和一个包含自定义组件的文件。我想从自定义控制器访问主文件组件,如下所示:

Main.fxml:

<FlowPane>
    <children>
        <TextField fx:id="source" />
        <CustomBox fx:id="cbox" />
    </children>
</FlowPane>

自定义.fxml:

<fx:root type="HBox">
    <children>
        <Button fx:id="showButton" onAction="#show" text="Show" />
    </children>
</fx:root>

CustomBox.java:

public class CustomBox extends HBox {
    @FXML
    private TextField source;

    public CustomBox() {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Custom.fxml"));
        loader.setRoot(this);
        loader.setController(this);
        try {
            loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @FXML
    protected void show() {
        System.out.println(source.getText());
    }
}

但是 show() 方法给了我 NPE。如何绑定来自不同文件的组件和控制器?

【问题讨论】:

  • 您不能将一个 FXML 文件中定义的控件注入到另一个 FXML 文件的控制器中 - 通常,将控件暴露在定义它们的 FXML 的控制器之外是不好的做法。相反,将主控制器的引用传递给自定义组件,并调用主控制器上的方法来检索文本(或使用 MVC 方法并定义模型类,并与两个控制器共享模型的实例)。

标签: java javafx fxml


【解决方案1】:

您可以为主 FXML 文件定义一个控制器,并从中公开文本:

public class MainController {

    @FXML
    private TextField source ;

    @FXML
    private CustomBox cbox ;

    public String getText() {
        return source.getText();
    }

    @FXML
    protected void initialize() {
        cbox.setMainController(this);
    }
}

当然也可以在Main.fxml 文件中将其指定为控制器类

<FlowPane fx:controller="my.package.MainController">
    <children>
        <TextField fx:id="source" />
        <CustomBox fx:id="cbox" />
    </children>
</FlowPane>

然后将你的CustomBox修改为

public class CustomBox extends HBox {

    private MainController mainController ;

    public CustomBox() {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Custom.fxml"));
        loader.setRoot(this);
        loader.setController(this);
        try {
            loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setMainController(MainController mainController) {
        this.mainController = mainController ;
    }

    public MainController getMainController() {
        return mainController ;
    }

    @FXML
    protected void show() {
        System.out.println(mainController.getText());
    }
}

我没有对此进行测试,但您也许可以在 FXML 文件中指定主控制器:

<FlowPane fx:controller="my.package.MainController">
    <children>
        <TextField fx:id="source" />
        <CustomBox fx:id="cbox" mainController="$controller" />
    </children>
</FlowPane>

然后在MainController中省略initialize()方法:

public class MainController {

    @FXML
    private TextField source ;

    public String getText() {
        return source.getText();
    }

}

【讨论】:

  • 谢谢,我明白了。
猜你喜欢
  • 1970-01-01
  • 2017-10-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多