JavaFX - 从子控制器到达主控制器

时间:2015-10-07 08:20:54

标签: java javafx

this page from oracle上解释了如何在主控制器中注入子控制器:

<VBox fx:controller="com.foo.MainController"> 
...
    <fx:include fx:id="dialog" source="dialog.fxml"/>
...
</VBox>

public class MainController extends Controller { 
    @FXML private Window dialog;
    @FXML private DialogController dialogController;

    ...

现在,我想知道如何从子控制器中取出MainController实例(在本例中为DialogController)。

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

我建议不要这样做。如果您的DialogController依赖于MainController,那么它就无法独立于MainController使用,这会在两者之间增加不必要的耦合(即它会破坏封装)。

MainController中的某个状态发生变化时,您可能只希望在DialogController中发生某些事情。因此,您应该将该状态公开为DialogController中的可观察属性,并从主控制器中观察它:

public class DialogController {

    private final ReadOnlyObjectWrapper<Person> selectedPerson = new ReadOnlyObjectWrapper<>();

    public ReadOnlyObjectProperty<Person> selectedPersonProperty() {
        return selectedPerson.getReadOnlyProperty();
    }

    public final Person getSelectedPerson() {
        return selectedPersonProperty().get();
    }

    @FXML
    private Button okButton ;

    public void initialize() {
        okButton.setOnAction(selectedPerson.set(new Person(...)));
    }
}

然后

public class MainController extends Controller { 
    @FXML private Window dialog;
    @FXML private DialogController dialogController;

    public void initialize() {
        dialogController.selectedPersonProperty().addListener((obs, oldPerson, newPerson) -> {
            // ... whatever you need to do here with new data when OK is pressed in dialog...
        });
    }
}

如果您确实想要访问MainController中的DialogController,那么您可以按照评论中的建议,通过&#34;手动&#34;将MainController注入DialogController。然而,这是糟糕的设计,imo。

public class DialogController {

    // Ugh. DialogController cannot be used outside the context where
    // MainController exists.
    private MainController mainController ;

    @FXML
    private Button okButton ;

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

    public void initialize() {
        okButton.setOnAction(e -> {
            if (mainController != null) {
                mainController.doSomething();
            }
        });
    }
}

并且

public class MainController {

    @FXML
    private DialogController dialogController ;

    public void initialize() {
        dialogController.setMainController(this);
    }

    public void doSomething() {
        // ...
    }
}