JavaFX从FXML子访问父控制器类

时间:2017-06-28 16:05:05

标签: java javafx fxml

将JavaFX用于应用程序,我有一个Main.fxml文件,里面有一些fxml子文件。

我想从子控制器访问Main.fxml的MainController类。

我试着用一个例子来解释一下:

MainFxml:

    <HBox fx:controller="MainController.java">
        <fx:include source="child.fxml"/>
    </HBox>

MainController:

    public class MainController implements Initializable {
            private String string;
            public void setString (String string) {
                    this.string = string;
            }

ChildFxml:

    <HBox fx:id="child" fx:controller="ChildController.java">
        <Button text="hello" onAction="#selectButton"></Button>
    </HBox>

ChildController:

    public class ChildController implements Initializable {
            @FXML HBox child;
            @FXML Button button;
            @FXML
            public void selectButton (ActionEvent event) {
                // here call MainController.setString("hello");
            }

我尝试this solution found on StackOverflow但我需要获取已经加载的Main.fxml的Controller引用。 是否有任何方法可以从特定的窗格启动Controller? 类似的东西:

    // child.getParent().getController();

2 个答案:

答案 0 :(得分:8)

如果您为fx:id标记分配<fx:include>,则FXMLLoader会尝试将包含的fxml的控制器注入名为<fx:id>Controller的字段。您可以使用MainController方法将initialize引用传递给子控制器:

<HBox fx:controller="MainController.java">
    <fx:include fx:id="child" source="child.fxml"/>
</HBox>

MainController

@FXML
private ChildController childController;

@Override
public void initialize(URL url, ResourceBundle rb) {
    childController.setParentController(this);
}

ChildController

private MainController parentController;

public void setParentController(MainController parentController) {
    this.parentController = parentController;
}

@FXML
private void selectButton (ActionEvent event) {
    this.parentController.setString("hello");
}

然而,更好的做法是让ChildController独立于父母。这可以通过在StringProperty中提供ChildController来设置父级应显示的值来完成。

ChildController

private final StringProperty value = new SimpleStringProperty();

public StringProperty valueProperty() {
    return value;
}

@FXML
private void selectButton (ActionEvent event) {
    value.set("hello");
}

ParentController

@Override
public void initialize(URL url, ResourceBundle rb) {
    childController.valueProperty().addListener((observable, oldValue, newValue) -> setString(newValue));
}

答案 1 :(得分:0)

我使用Singleton模型在我自己的项目中解决了这个问题。您可以使用单独的类来保持对父控制器的引用。

例如:

<强> Global.java:

public class Global {

    public static ParentControllerClass parentController;

    private Global() {
    }

    public static ParentControllerClass getParentController() {
        return mainApp;
    }

    public static void setParentController(ParentControllerClass parentController) {
        Global.parentController = parentController;
    }
}

在您的父控制器中,您只需要通过调用Global将引用传递给Global.setParentController(this);类。然后,您可以使用Getter:Global.getParentController();

从孩子访问它

这比父母和孩子共享相同的控制器更有利,因为它有助于保持代码更清晰,更易于阅读。

我自己对Java很新,这对于这种情况可能不是最复杂的方法,但到目前为止它对我来说非常有效。