Reputation: 1358
I have a stage that has a TabPane tabPane
inside it, with one "main" tab and a HashMap<Connection,Tab> connectionTabs
of other tabs (Connection
is a custom class).
I implement those tabs dynamically.
@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();
}
}
Now, in the connectionTab.fxml
I declare a controller (ConnectionTabController
).
How can I access this tabs controller from this class? Or do I have to it another way?
I'm stuck at:
@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();??? */
}
}
It's only logical to me that it's somewhere within the Content
(since I'm setting it up earlier), but I still can't find out how to reach it, or if it's even possible.
Any sort of help is more than welcome!
Upvotes: 1
Views: 1586
Reputation: 209225
You can retrieve the controller when you load the FXML:
try {
Tab tab = new Tab();
//...
FXMLLoader loader = new FXMLLoader(getClass().getResource("../fxml/connectionTab.fxml"));
tab.setContent(loader.load());
ConnectionTabController controller = loader.getController();
// ...
}
and then just store it or pass it to wherever it's needed.
Another option might be to use this pattern. In this case you would do:
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...
}
Update your fxml as
<!-- imports etc ommitted -->
<!-- note no fx:controller.... -->
<fx:root type="javafx.scene.control.Tab" xmlns:fx="...">
<content>
<!-- layout here -->
</content>
</fx:root>
And now in your other code you do
@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();
}
}
Now the connectionTabs
map gives you direct access to the controller methods via the value objects in it.
Note that with this solution, it's very easy to pass references to the ConnectionTab
, if you need that:
public class ConnectionTab {
private final Connection connection ;
// ...
public ConnectionTab(Connection connection) {
this.connection = connection ;
try {
// load FXML as before...
} catch (Exception e) { ... }
}
// ...
}
Upvotes: 2