繁体   English   中英

JavaFX:使垂直ScrollBar适合TableView中的父节点

[英]JavaFX: make a vertical ScrollBar fit to parent node in TableView

我有一个垂直滚动的TableView,并且我希望ScrollBar扩展到其父AnchorPane的顶部,并位于右上角的填充正方形的顶部。 默认情况下,请参见下文。 请注意,我的填充节点为白色,而不是右上角的表格列。

在此处输入图片说明

在这行下面是我想要的,由另一个程序正确实现。

在此处输入图片说明

我能够做到这一点

Platform.runLater(() ->
{
    ScrollBar someScrollBar = (ScrollBar) someTable.lookup(".scroll-bar:vertical");
    someScrollBar.setTranslateY(-12);
    someScrollBar.setScaleY(1.2);
}
);

其中someTable是用FXML制成的TableView,并在控制器的初始化函数中引用。

在此处输入图片说明

这样看起来不错,但无法正确缩放。 如果包含的AnchorPane垂直调整大小,则看起来很糟糕。

谁能建议一个更好的方法来做到这一点?

非常感谢您的参与。

不支持scrollBars的自定义布局。 我最初的评论是,需要一个带有自定义TableHeaderRow的自定义TableViewSkin:后者负责管理..好 ,不幸的是,tableHeader只是故事的一部分。

  • 一个TableHeaderRow确实负责布局表头
  • 但是:TableHeaderRow无法对垂直滚动条进行布局-当它尝试在覆盖的layoutChildren()进行布局时,它将立即重置
  • 重置发生在VirtualFlow中(这是scrollBar的父级)

所以最终,我们需要

  • 一个定制的TableHeaderRow,表示需要放大和重新定位scrollBar:以下示例设置了一个滚动条,如果该滚动条是可见的(tbd:检查menuButton是否可见),则在该滚动条的属性图中具有所需的附加高度
  • 一个可以处理标记并根据需要实际进行布局的自定义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());

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM