JavaFX - 访问动态创建的选项卡的控制器

JavaFX - accessing a dyinamically created tab's controller

我有一个舞台,里面有一个 TabPane tabPane,有一个 "main" 选项卡和 HashMap<Connection,Tab> connectionTabs 个其他选项卡(Connection 是一个自定义 class).

我动态实现这些选项卡。

@Override
public void connectionCreatedEvent(Connection connection) {
    try {
        Tab tab = new Tab();
        //...
        tab.setContent(FXMLLoader.load(getClass().getResource("../fxml/connectionTab.fxml")));
        Platform.runLater(() -> {
            tabPane.getTabs().add(tab);
            tabPane.getSelectionModel().select(tab);
        });
        connectionTabs.put(connection, tab);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

现在,在 connectionTab.fxml 中我声明了一个控制器 (ConnectionTabController)。

如何从这个 class 访问这个选项卡控制器?还是我必须换一种方式?

我被困在:

@Override
public void connectionLogEvent(Connection connection, String msg) {
    System.out.println("-t-connection log : " + connection + " : " + msg);
    for(Object o : connectionTabs.entrySet()) {
        Map.Entry ct = (Map.Entry)o;
        if(ct.getKey() == connection)
            /* ???(Tab)ct.getKey().getController();??? */
    }
}

我觉得它在 Content 中的某个地方是合乎逻辑的(因为我之前设置了它),但我仍然无法找到如何到达它,或者是否可能。

我们非常欢迎任何形式的帮助!

您可以在加载 FXML 时检索控制器:

try {
    Tab tab = new Tab();
    //...
    FXMLLoader loader = new FXMLLoader(getClass().getResource("../fxml/connectionTab.fxml"));
    tab.setContent(loader.load());

    ConnectionTabController controller = loader.getController();

    // ...
}

然后将其存储或传递到任何需要的地方。

另一种选择可能是使用 this pattern。在这种情况下你会这样做:

public class ConnectionTab extends Tab {

    // @FXML-annotated controls...


    public ConnectionTab() {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("../fxml/connectionTab.fxml"));
            loader.setRoot(this);
            loader.setController(this);
            loader.load();
        } catch (Exception exc) {
            // ...
        }
    }

    // controller methods, etc...
}

将您的 fxml 更新为

<!-- imports etc ommitted -->

<!-- note no fx:controller.... -->
<fx:root type="javafx.scene.control.Tab" xmlns:fx="...">
    <content>
        <!-- layout here -->
    </content>
</fx:root>

现在在你的其他代码中你做

@Override
public void connectionCreatedEvent(Connection connection) {
    try {
        ConnectionTab tab = new ConnectionTab();
        //...

        Platform.runLater(() -> {
            tabPane.getTabs().add(tab);
            tabPane.getSelectionModel().select(tab);
        });
        connectionTabs.put(connection, tab);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

现在 connectionTabs 映射让您可以通过其中的值对象直接访问控制器方法。

请注意,使用此解决方案,可以很容易地传递对 ConnectionTab 的引用,如果您需要的话:

public class ConnectionTab {

    private final Connection connection ;

    // ...

    public ConnectionTab(Connection connection) {
        this.connection = connection ;
        try {

            // load FXML as before...

        } catch (Exception e) { ... }

    }

    // ...
}