I\'d like to use a (JavaFX) TabPane to display the content of 20 different tabs. This works fine with the standard TabPane, however, when the pane hits a certain amount of tabs,
The tab header area for TabPane
is basically a StackPane, therefore I think it is not so easy to create two rows of tabs instead of one.
My idea is to hide the original tabs of your TabPane
and put a set of ToggleButton
objects in a ToggleGroup
then bind the selection of toggles with the selection of tabs.
This way you could add the "Tabs" into any container you want (flow, grid, etc).
Really minimal sample:
Main.java
public class Main extends Application {
TabPane tabPane;
private ToggleGroup toggleGroup;
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Scene scene = new Scene(root, 700, 400, Color.WHITE);
primaryStage.setTitle("Tabs Test");
toggleGroup = new ToggleGroup();
toggleGroup.selectedToggleProperty().addListener(new ChangeListener() {
@Override
public void changed(ObservableValue extends Toggle> observable, Toggle oldValue, Toggle newValue) {
if (newValue == null)
toggleGroup.selectToggle(oldValue);
else
tabPane.getSelectionModel().select((Tab) newValue.getUserData());
}
});
tabPane = new TabPane();
tabPane.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
VBox vboxToggleOuterContainer = new VBox();
HBox hboxToggleFirstRow = new HBox();
HBox hboxToggleSecondRow = new HBox();
vboxToggleOuterContainer.getChildren().addAll(hboxToggleFirstRow, hboxToggleSecondRow);
for (int i = 0; i < 20; i++) {
Tab tab = new Tab();
tab.setText("Tab " + i);
HBox hbox = new HBox();
hbox.getChildren().add(new Label("Tab " + i));
tab.setContent(hbox);
tabPane.getTabs().add(tab);
ToggleButton tb = new ToggleButton("Tab" + i);
tb.setToggleGroup(toggleGroup);
tb.setUserData(tab);
if (i < 10)
hboxToggleFirstRow.getChildren().add(tb);
else
hboxToggleSecondRow.getChildren().add(tb);
}
toggleGroup.selectToggle(toggleGroup.getToggles().get(0));
VBox vbox = new VBox();
vbox.getChildren().addAll(vboxToggleOuterContainer, tabPane);
vbox.fillWidthProperty().set(true);
root.getChildren().add(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
application.css
.tab-pane {
-fx-skin: "com.sun.javafx.scene.control.skin.TabPaneSkin";
-fx-tab-min-height: 0;
-fx-tab-max-height: 0;
}
.tab-pane .tab-header-area {
-fx-padding: 0 0 0 0;
}
.tab-pane .tab-header-area .headers-region .tab {
-fx-padding: 0 0 1 0;
}
The example is really minimal, just shows the approach, you can improve the CSS to have the control much more fancy (or if you want I can also update it if I will have time).