如何使用TabPane作为内容按需获取滚动条?

时间:2019-03-27 10:31:55

标签: javafx resize scrollpane

我在ScrollPane的Tabpane内有一个BorderPane。如果我删除TabPane并将BorderPane作为ScrollPane的内容,则ScrollPane.ScrollBarPolicy.AS_NEEDED确实可以工作。我如何使它与TabPane一起使用?

BorderPane能够以某种方式告诉ScrollPane何时显示滚动条,而TabPane无法这样做。我浏览了Tabpane的可用方法,但是找不到任何用于此大小调整的方法。

工作示例:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class FXApplication extends Application {

    private BorderPane border;
    private GridPane inner;
    private TabPane tabPane;

    @Override
    public void start(Stage primaryStage) {

        tabPane = new TabPane();
        Tab tab = new Tab("test");
        tabPane.getTabs().add(tab);

        border = new BorderPane();
        border.setCenter(innerGrid());
        tab.setContent(border);

        ScrollPane scp = new ScrollPane();
        scp.setFitToHeight(true);
        scp.setFitToWidth(true);
        scp.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
        scp.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);

//        scp.setContent(border);  // this works
        scp.setContent(tabPane);   // this doesnt

        Scene s = new Scene(scp);
        primaryStage.setScene(s);
        primaryStage.show();
    }

    private GridPane innerGrid() {
        inner = new GridPane();

        for(int i=0; i<11 ;i++) {
            ColumnConstraints columnConstraints = new ColumnConstraints();
            columnConstraints.setHgrow(Priority.SOMETIMES);
            inner.getColumnConstraints().add(columnConstraints);

            RowConstraints rowConstraints = new RowConstraints();
            rowConstraints.setVgrow(Priority.SOMETIMES);
            inner.getRowConstraints().add(rowConstraints);
        }

        for(int i=0; i<100 ;i++) {
            inner.add(new Button("Button " + i), i/10, i%10);
        }

        return inner;
    }

    public static void main(String[] args) {
        FXApplication.launch(args);
    }

}

1 个答案:

答案 0 :(得分:1)

令人惊讶的是,未指定AS_NEEDED的确切行为。我们所拥有的只是要查看的ScrollPaneSkin。是否显示(f.i.)单杠的决定是通过其私有方法determineHorizontalSBVisible()

进行的
private boolean determineHorizontalSBVisible() {
    final ScrollPane sp = getSkinnable();

    if (Properties.IS_TOUCH_SUPPORTED) {
        return (tempVisibility && (nodeWidth > contentWidth));
    }
    else {
        // RT-17395: ScrollBarPolicy might be null. If so, treat it as "AS_NEEDED", which is the default
        ScrollBarPolicy hbarPolicy = sp.getHbarPolicy();
        return (ScrollBarPolicy.NEVER == hbarPolicy) ? false :
               ((ScrollBarPolicy.ALWAYS == hbarPolicy) ? true :
               ((sp.isFitToWidth() && scrollNode != null ? scrollNode.isResizable() : false) ?
               (nodeWidth > contentWidth && scrollNode.minWidth(-1) > contentWidth) : (nodeWidth > contentWidth)));
    }
}

在这里,nodeWidth是内容节点的实际宽度-先前已计算,并考虑了该节点的最小/最大宽度-而contentWidth是可用于布置内容的宽度。

对我来说不可读的代码(对于我来说;)如果内容的实际宽度和最小宽度都大于可用宽度,则在调整内容大小并适合scrollPane的内容区域时,归结为返回true。

minWidth使您的上下文有所不同:BorderPane具有min > 0,TabPane具有min == 0,因此上述方法始终返回false。

反之亦然:要使hbar在TabPane中可见,它需要一个最小值f.i。通过将其与其首选项相关联:

tabPane.setMinWidth(Region.USE_PREF_SIZE);