Reputation: 173
I have a JavaFX app with the following Node layout:
Example Code:
SplitPane topBottomSplitPane = new SplitPane();
TextArea displayTextArea = new TextArea();
SplitPane leftRightSplitPane = new SplitPane();
topBottomSplitPane.getItems().addAll(displayTextArea, leftRightSplitPane);
TabPane leftTabPane = new TabPane();
TabPane rightTabPane = new TabPane();
leftRightSplitPane.getItems().addAll(leftTabPane, rightTabPane);
The TextArea, displayTextArea, is an non-editable text area that displays some text-data depending upon what data is present in the opened Tab objects inside the two TabPanes, leftTabPane and rightTabPane. The TabPane's SelectionModel is singular so that only one Tab may be selected at a time per TabPane.
One of the constraints I have is that only one of the open Tab objects data should be influencing displayTextArea's text. This was easy to accomplish when there was only one TabPane object by setting a OnSelectionChanged EventHandler and using isSelected() to determine if the change of selection was either a change into or out of selection. And the selected Tab would be the one influencing displayTextArea.
When there are two TabPanes I would want the Tab who's Content Node currently has focus, say a TextField or form where the user is entering data that will affect the text of displayTextArea. The way it would look from a user's perspective is they will be clicking through the open Tabs in both the TabPanes and the last one they clicked on would be influencing displayTextArea. But that is where I am running into a wall.
Attempted and Failed Approaches:
Setup some kind of listener to be notified of a change in focus from one of the Tab's content Node into another Tab's content Node, regardless of which TabPane they are in, then update the displayTextArea accordingly. - There is no AddFocusListener method and I am unsure how to work with the available focus oriented methods and functionality to achieve this behavior.
Force only 1 Tab to be selected at any one time between multiple TabPanes and stick with the aforementioned OnSelectionChanged EventHandler approach. - I don't know where to start on this one and I have not been able to find anything on it.
In this question there is the topic of changing focus into a TextField object in the Tab's Content Node but I was unable to grab anything useful for my purpose from that post.
I am lost here and don't know how to implement the necessary functionality for this display.
Upvotes: 2
Views: 8129
Reputation: 47
I achieved a simple solution using FXML onSelectionChange methods as follows.
First, I'll consider that there's a single controller for the whole pane, so it doesn't matter where or how many tabs you're using.
For each tab, on the FXML (could be coded), I added an onSelectionChanged listener method. The problem is that after any tab selection, JavaFX notifies the two involved tabs (in this order): the new selected tab, and the previously selected one. So, I just put a boolean variable to flag whether this is the first or the second call.
NOTE: Be aware that this solution might be risky if this notification policy changes in the future.
Part of my Controller Code:
private boolean tabSelection = false;
@FXML void reportsTabSelected(Event e) {
if (checkTab()) {
System.out.println("Reports Tab is Now Selected");
}
}
@FXML void configTabSelected(Event e) {
if (checkTab()) {
System.out.println("Configs Tab is Now Selected");
}
}
private boolean checkTab() {
tabSelection = !tabSelection;
return tabSelection;
}
Part of the Tabs FXML:
<Tab text="REPORTS" fx:id="reportsTab" onSelectionChanged="#reportsTabSelected">
</Tab>
<Tab text="CONFIGURATIONS" fx:id="configurationsTab" onSelectionChanged="#configTabSelected">
</Tab>
Upvotes: 0
Reputation: 173
I came up with a reasonable and fairly simple solution:
Problem Use-case: (See image posted in question for use-case reference)
The problem with the above use-case is that both Tab1 and Tab4 are the currently selected Tabs for their respective TabPanes. Thus no Tab's have their isSelected boolean changed, and their onSelectionChanged EventHandler is not fired.
The solution:
If anyone needs more explination or would benefit from a coded example implementation of this algorithm just leave a comment asking for it and I will throw one together for you real quick.
Upvotes: 2
Reputation: 3649
Since the displayTextArea can only show content related to one of the four tabs at a time you shouldn't need to try to link the two sets of tabs together. Instead each of the tab panes can have its own response to a selection change. The only commonality between them will be that all of the selection changes will call into the same method that populates the displayTextArea. For the purposes of this example lets call that method setDisplayTextAreaContent, lets also assume that by passing that method the most recently selected tab it would know how to populate the displayTextArea. After making these assumptions, and the assumption that I understood your question correctly, the solution could look something like this...
TabPane tabPane1 = new TabPane();
final Tab tab1 = new Tab();
final Tab tab2 = new Tab();
tabPane1.getTabs().addAll(tab1, tab2);
tabPane1.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>()
{
@Override
public void changed(ObservableValue<? extends Tab> arg0, Tab arg1, Tab mostRecentlySelectedTab)
{
if (mostRecentlySelectedTab.equals(tab1))
{
setDisplayTextAreaContent(tab1);
}
if (mostRecentlySelectedTab.equals(tab2))
{
setDisplayTextAreaContent(tab2);
}
}
});
TabPane tabPane2 = new TabPane();
final Tab tab3 = new Tab();
final Tab tab4 = new Tab();
tabPane2.getTabs().addAll(tab1, tab2);
tabPane2.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>()
{
@Override
public void changed(ObservableValue<? extends Tab> arg0, Tab arg1, Tab mostRecentlySelectedTab)
{
if (mostRecentlySelectedTab.equals(tab3))
{
setDisplayTextAreaContent(tab3);
}
if (mostRecentlySelectedTab.equals(tab4))
{
setDisplayTextAreaContent(tab4);
}
}
});
You could instead add a listener to the selectedIndexProperty of the TabPanes if that works better for you (assuming you would know which tabs are at what index within their respective TabPanes). I hope this answer helps you out. Let me know if you have any questions and I'd be happy to answer them if I can.
Upvotes: 0