Javafx TabPane with multiple rows of tabs

前端 未结 1 1408
萌比男神i
萌比男神i 2021-01-24 06:20

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,

1条回答
  •  余生分开走
    2021-01-24 06:42

    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 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).

    0 讨论(0)
提交回复
热议问题