JavaFX控制器与动态内容的通信

时间:2018-01-25 02:40:13

标签: javafx fxml

这是我正在创建的JavaFX android移动应用程序的一般结构。 使用(AppBar或AppBarSearch动态交换)作为主应用程序FXML中的嵌套控制器。

ParentController   - AppBarController   - AppBarSearchController

primary.fxml   - appBar.fxml / appBarSearch.fxml

    <AnchorPane fx:id="appBarPane" prefHeight="56.0" prefWidth="350.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
        <children>
            <fx:include source="appbar.fxml" fx:id="appBar" /> 
    <!-- initially shows AppBar but appBarSearch can also be here after clicking search button -->
        </children>
    </AnchorPane>

每个子fxml中的一个按钮负责在appBar / AppBarSearch中更改fxml内容。

当我动态地将appBar的内容更改为appBarSearch并返回时,会出现此问题。我希望appBar菜单按钮与NavigationMenu进行通信以进行滑入和滑出。

我一直在研究是否应该在AppBarController中以某种方式拥有parentController的实例。

我确实使用了以下内容:

@FXML
private AppBarController appBarController; // injected via <fx:include fx:id="child" ... />

<fx:include source="appbar.fxml" fx:id="appBar" /> <- dynamically changes

//to dynamically change content in Panes
public static void setView(View view, Pane pane) {
    try {
        pane.getChildren().clear();
        pane.getChildren().setAll((Node) FXMLLoader.load(Main.class.getResource(view.getTemplate()), resources));
    } catch (IOException e) {
        logger.error(e.getMessage());
    }
}

    @FXML
public void initialize() {
    appBarController.setParentController(this);
}

    @FXML
private void menuButtonClick (ActionEvent event) {
    this.parentController.triggerMenu();
}

最初上面有效,但在appBarSearch和appBar之间切换后,它给了我一个nullPointer到parentController实例。

可能是在动态切换控制器之后,它无法识别子控制器。

我希望AppBar中的menuBtn打开一个navigationMenu,因此需要在PrimaryController中调用triggerMenu(),以便在单击AppBar中的按钮后开始滑动和滑出动画。

1 个答案:

答案 0 :(得分:0)

非常感谢评论,我能够解决问题并提高我对如何使用控制器和包含fxml的理解。 下面是我用来连接子控制器和我的主控制器并动态更改视图的一般代码。

@FXML
private AppBarController appBarController; // injected via <fx:include fx:id="child" ... />

@FXML
private NavMenuController navMenuController; // injected via <fx:include fx:id="child" ... />

@FXML
private MainContentController mainContentController; // injected via <fx:include fx:id="child" ... />

@FXML
public void initialize() {
    appBarController.setScreenParent(this);
    navMenuController.setScreenParent(this);
    mainContentController.setScreenParent(this);
}

/**
 * Set View on a Pane Javafx component
 */
public <T extends Pane> boolean setView(View view, T pane) {
    try {
        FXMLLoader myLoader = new FXMLLoader(getClass().getResource(view.getTemplate()), resources);
        pane.getChildren().clear();
        pane.getChildren().setAll((Node) myLoader.load());
        ControlledScreen childController = myLoader.getController();
        childController.setScreenParent(this);
        return true;
    } catch (IOException e) {
        logger.error(e.getMessage());
        return false;
    }
}

public void setMainContentView(View view) {
    setView(view, mainContentPane);
}

public void setAppBarView(View view) {
    setView(view, appBarPane);
}

public void setNavMenuView(View view) {
    setView(view, navMenuPane);
}

public void triggerNavMenu() {
    if (navMenuPane.getTranslateX() != 0) {
        openNav.play();
        appBarController.setMenuClosedImage();
    } else {
        closeNav.setToX(-(navMenuPane.getWidth()));
        closeNav.play();
        appBarController.setMenuClosedImage();
    }
}