#java #css #javafx
#java #css #javafx
Вопрос:
У меня есть TableView, который прокручивается вертикально, и я хотел бы, чтобы полоса прокрутки простиралась до верха родительской панели привязки и находилась поверх заполняющего квадрата в правом верхнем углу. Смотрите ниже, на что это похоже по умолчанию. Обратите внимание, что мой узел-заполнитель белый, это не столбец таблицы в правом верхнем углу.
и под этой строкой то, что я хочу, правильно реализовано другой программой.
Я смог добиться этого, выполнив
Platform.runLater(() ->
{
ScrollBar someScrollBar = (ScrollBar) someTable.lookup(".scroll-bar:vertical");
someScrollBar.setTranslateY(-12);
someScrollBar.setScaleY(1.2);
}
);
где someTable
— это TableView, созданный в FXML и упоминаемый в функции инициализации контроллера.
Это выглядит нормально, но масштабируется неправильно. Если содержащая анкерная панель изменяется по вертикали, это выглядит ужасно.
Кто-нибудь может предложить лучший способ сделать это?
Большое вам спасибо за ваше время.
Комментарии:
1. вам нужен пользовательский TableViewSkin с пользовательским TableHeaderRow: последний отвечает за управление .. ну, TableHeader 🙂
Ответ №1:
Пользовательское расположение полос прокрутки не поддерживается. И мой первоначальный комментарий вам нужен пользовательский TableViewSkin с пользовательским TableHeaderRow: последний отвечает за управление .. ну, TableHeader, к сожалению, это только часть истории.
- TableHeaderRow действительно отвечает за размещение заголовка таблицы
- но: TableHeaderRow ничего не может сделать для разметки вертикальной полосы прокрутки — когда он пытается сделать это в переопределенном
layoutChildren()
, он немедленно сбрасывается - сброс происходит в VirtualFlow (который является родительским для полосы прокрутки)
Итак, в конце дня нам нужно
- пользовательский TableHeaderRow, который сигнализирует о необходимости увеличения и перемещения полосы прокрутки: приведенный ниже пример устанавливает маркер, если полоса прокрутки видна (tbd: проверьте, видна ли кнопка меню), с требуемой дополнительной высотой на карте свойств полосы прокрутки
- пользовательский VirtualFlow, который может обрабатывать маркер и фактически выполняет разметку по мере необходимости: приведенный ниже пример проверяет наличие маркера и при необходимости изменяет размер / перемещение полосы прокрутки.
- пользовательский TableViewSkin для внедрения обоих (с помощью переопределенных заводских методов)
Пример написан для fx11, должен работать для fx10, но не для fx9, потому что последний не позволяет предоставлять пользовательский VirtualFlow:
public class TableWithoutCorner extends Application {
/**
* Custom TableHeaderRow that requests a larger vbar height
* if needed.
*/
private static class MyTableHeader extends TableHeaderRow {
private Region cornerAlias;
private ScrollBar vBar;
private TableViewSkinBase skin;
public MyTableHeader(TableViewSkinBase skin) {
super(skin);
this.skin = skin;
}
@Override
protected void layoutChildren() {
super.layoutChildren();
adjustCornerLayout();
}
private void adjustCornerLayout() {
checkAlias();
// tbd: check also if corner is visible
if (!vBar.isVisible()) {
vBar.getProperties().remove("DELTA");
} else {
vBar.getProperties().put("DELTA", getHeight());
}
}
private void checkAlias() {
if (cornerAlias == null) {
cornerAlias = (Region) lookup(".show-hide-columns-button");
}
if (vBar == null) {
vBar = (ScrollBar) skin.getSkinnable().lookup(".scroll-bar:vertical");
}
}
}
/**
* Custom VirtualFlow that respects additinal height for its
* vertical ScrollBar.
*/
private static class MyFlow extends VirtualFlow {
private ScrollBar vBar;
private Region clip;
public MyFlow() {
// the scrollbar to adjust
vBar = (ScrollBar) lookup(".scroll-bar:vertical");
// the clipped container to use for accessing viewport dimensions
clip = (Region) lookup(".clipped-container");
}
/**
* Overridden to adjust vertical scrollbar's height and y-location
* after calling super.
*/
@Override
protected void layoutChildren() {
super.layoutChildren();
adjustVBar();
}
/**
* Adjusts vBar height and y-location by the height as
* requested by the table header.
*/
protected void adjustVBar() {
if (vBar.getProperties().get("DELTA") == null) return;
double delta = (double) vBar.getProperties().get("DELTA");
vBar.relocate(clip.getWidth(), - delta);
vBar.resize(vBar.getWidth(), clip.getHeight() delta);
}
}
/**
* Boilerplate: need custom TableViewSkin to inject a custom TableHeaderRow and
* custom VirtualFlow.
*/
private static class MyTableViewSkin<T> extends TableViewSkin<T> {
public MyTableViewSkin(TableView<T> control) {
super(control);
}
@Override
protected TableHeaderRow createTableHeaderRow() {
return new MyTableHeader(this);
}
@Override
protected VirtualFlow<TableRow<T>> createVirtualFlow() {
return new MyFlow();
}
}
private Parent createContent() {
TableView<Locale> table = new TableView<>(FXCollections.observableArrayList(Locale.getAvailableLocales())) {
@Override
protected Skin<?> createDefaultSkin() {
return new MyTableViewSkin(this);
}
};
TableColumn<Locale, String> col = new TableColumn<>("Name");
col.setCellValueFactory(new PropertyValueFactory<>("displayName"));
table.getColumns().addAll(col);
return table;
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
//stage.setTitle(FXUtils.version());
stage.show();
}
public static void main(String[] args) {
launch(args);
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(TableWithoutCorner.class.getName());
}