如何从不同的文件控制器访问组件?

时间:2017-05-25 12:35:01

标签: java javafx fxml

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

Main.fxml:

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

Custom.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。如何从不同的文件绑定组件和控制器?

1 个答案:

答案 0 :(得分:0)

您可以为主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>

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

public class MainController {

    @FXML
    private TextField source ;

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

}