Как получить полосы прокрутки по мере необходимости с TabPane в качестве контента? - PullRequest
3 голосов
/ 27 марта 2019

У меня есть BorderPane внутри Tabpane внутри ScrollPane. ScrollPane.ScrollBarPolicy.AS_NEEDED работает, если я удаляю TabPane и помещаю BorderPane в качестве содержимого ScrollPane. Как мне заставить это работать с 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 Ответ

1 голос
/ 27 марта 2019

Удивительно, но точное поведение AS_NEEDED не указано.Все, что у нас есть, это ScrollPaneSkin, чтобы посмотретьРешение о том, показывать или нет горизонтальную полосу (fi), происходит в ее частном методе 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 - это фактическая ширина узла контента - был вычислен ранее с учетом минимума узла/ max widths - и contentWidth - это ширина, доступная для размещения контента.

Нечитаемый код (для меня;) В случае изменяемого размера контента и встраивания в область содержимого scrollPane сводится к возврату true, если оба содержимого актуальныи min ширина больше доступной ширины.

minWidth имеет значение в вашем контексте: BorderPane имеет min > 0, TabPane имеет min == 0, поэтому приведенный выше метод всегда возвращает false.

С другой стороны: чтобы позволить hbar быть видимым с TabPane, ему нужно min, fi, связав его с префом:

tabPane.setMinWidth(Region.USE_PREF_SIZE);
...