【问题标题】:JavaFX controller communication with dynamic contentJavaFX 控制器与动态内容的通信
【发布时间】:2018-01-26 19:55:36
【问题描述】:

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

父控制器 - 应用栏控制器 - 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 之间切换后,它给了我一个指向 parentController 实例的 nullPointer。

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

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

【问题讨论】:

  • 这里有几个类似的问题,但我现在无法通过快速搜索找到它们。基本思想是创建一个具有描述当前显示屏幕的属性的模型类。然后您的主视图可以观察该属性并更新视图(将旧视图转换出并转换新视图等),而您的其他视图可以通过设置属性间接修改主视图。 Angela Caciedo 有一个框架可以做到这一点:她以前有一个关于 Oracle 的博客,现在已经消失了,但是在 github.com/acaicedo?tab=repositories 有一个 repo 和一个视频(上图!)。
  • 解决方案在我看来是微不足道的。如果视图可以使用通用控制器,只需将其注入FXMLLoader 的上下文中。否则,请保留您在创建新项目时注入或从FXMLLoader 接收的控制器实例。
  • 这是另一个类似的问题:stackoverflow.com/questions/46915578/…

标签: javafx fxml


【解决方案1】:

非常感谢 cmets,我能够解决问题并提高我对如何使用控制器和包含 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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-05
    • 2014-04-06
    • 2010-12-19
    • 2013-04-05
    • 2019-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多