猿问

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

我有一个垂直滚动的 TableView,我希望 ScrollBar 延伸到其父 AnchorPane 的顶部,并位于右上角填充方块的顶部。请参阅下文,了解默认情况下的情况。请注意,我的填充节点是白色的,这不是右上角的表列。

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

http://img2.mukewang.com/62e9fd4700016c8702510193.jpg

我能够通过以下方法实现这一目标:


Platform.runLater(() ->

{

    ScrollBar someScrollBar = (ScrollBar) someTable.lookup(".scroll-bar:vertical");

    someScrollBar.setTranslateY(-12);

    someScrollBar.setScaleY(1.2);

}

);

其中 是在 FXML 中创建的表视图,在控制器初始化函数中引用。someTable

http://img.mukewang.com/62e9fd520001188402750164.jpg

它看起来很好,但它不能正确缩放。如果包含的 AnchorPane 垂直调整大小,它看起来很糟糕。

任何人都可以建议更好的方法来做到这一点吗?

非常感谢您抽出宝贵时间接受采访。


郎朗坤
浏览 312回答 1
1回答

哔哔one

不支持滚动条的自定义布局。我最初的评论是,你需要一个带有自定义TableHeaderRow的自定义TableViewSkin:不幸的是,后者负责管理......好吧,tableHeader只是故事的一部分。一个 TableHeaderRow 确实负责布置表头但是:TableHeaderRow无法对垂直滚动条进行布局 - 当它试图在被覆盖中这样做时,它会立即重置layoutChildren()重置发生在VirtualFlow(它是滚动条的父级)中因此,在一天结束时,我们需要一个自定义的 TableHeaderRow,表示需要放大和重新定位 scrollBar:下面的示例设置一个标记,如果 scrollBar 可见(待定:检查菜单按钮是否可见),并在 scrollBar 的属性映射中设置所需的额外高度一个自定义的VirtualFlow,可以处理标记并根据需要实际进行布局:下面的示例检查标记并在需要时调整大小/重新定位滚动条。一个自定义的 TableViewSkin 来注入两者(通过重写的工厂方法)该示例是针对 fx11 编写的,应该适用于 fx10,但不适用于 fx9,因为后者不允许提供自定义 VirtualFlow:public class TableWithoutCorner extends Application {&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* Custom TableHeaderRow that requests a larger vbar height&nbsp; &nbsp; &nbsp;* if needed.&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; private static class MyTableHeader extends TableHeaderRow {&nbsp; &nbsp; &nbsp; &nbsp; private Region cornerAlias;&nbsp; &nbsp; &nbsp; &nbsp; private ScrollBar vBar;&nbsp; &nbsp; &nbsp; &nbsp; private TableViewSkinBase skin;&nbsp; &nbsp; &nbsp; &nbsp; public MyTableHeader(TableViewSkinBase skin) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super(skin);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.skin = skin;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; protected void layoutChildren() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.layoutChildren();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; adjustCornerLayout();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private void adjustCornerLayout() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkAlias();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // tbd: check also if corner is visible&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!vBar.isVisible()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; vBar.getProperties().remove("DELTA");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; vBar.getProperties().put("DELTA", getHeight());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private void checkAlias() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (cornerAlias == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cornerAlias = (Region) lookup(".show-hide-columns-button");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (vBar == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; vBar = (ScrollBar) skin.getSkinnable().lookup(".scroll-bar:vertical");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* Custom VirtualFlow that respects additinal height for its&nbsp;&nbsp; &nbsp; &nbsp;* vertical ScrollBar.&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; private static class MyFlow extends VirtualFlow {&nbsp; &nbsp; &nbsp; &nbsp; private ScrollBar vBar;&nbsp; &nbsp; &nbsp; &nbsp; private Region clip;&nbsp; &nbsp; &nbsp; &nbsp; public MyFlow() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // the scrollbar to adjust&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; vBar = (ScrollBar) lookup(".scroll-bar:vertical");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // the clipped container to use for accessing viewport dimensions&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; clip = (Region) lookup(".clipped-container");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Overridden to adjust vertical scrollbar's height and y-location&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* after calling super.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; protected void layoutChildren() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.layoutChildren();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; adjustVBar();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Adjusts vBar height and y-location by the height as&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* requested by the table header.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; &nbsp; &nbsp; protected void adjustVBar() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (vBar.getProperties().get("DELTA") == null) return;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; double delta = (double) vBar.getProperties().get("DELTA");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; vBar.relocate(clip.getWidth(), - delta);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; vBar.resize(vBar.getWidth(), clip.getHeight() + delta);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* Boilerplate: need custom TableViewSkin to inject a custom TableHeaderRow and&nbsp; &nbsp; &nbsp;* custom VirtualFlow.&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; private static class MyTableViewSkin<T> extends TableViewSkin<T> {&nbsp; &nbsp; &nbsp; &nbsp; public MyTableViewSkin(TableView<T> control) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super(control);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; protected TableHeaderRow createTableHeaderRow() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new MyTableHeader(this);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; protected VirtualFlow<TableRow<T>> createVirtualFlow() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new MyFlow();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; private Parent createContent() {&nbsp; &nbsp; &nbsp; &nbsp; TableView<Locale> table = new TableView<>(FXCollections.observableArrayList(Locale.getAvailableLocales())) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; protected Skin<?> createDefaultSkin() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new MyTableViewSkin(this);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; TableColumn<Locale, String> col = new TableColumn<>("Name");&nbsp; &nbsp; &nbsp; &nbsp; col.setCellValueFactory(new PropertyValueFactory<>("displayName"));&nbsp; &nbsp; &nbsp; &nbsp; table.getColumns().addAll(col);&nbsp; &nbsp; &nbsp; &nbsp; return table;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public void start(Stage stage) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; stage.setScene(new Scene(createContent()));&nbsp; &nbsp; &nbsp; &nbsp; //stage.setTitle(FXUtils.version());&nbsp; &nbsp; &nbsp; &nbsp; stage.show();&nbsp; &nbsp; }&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; launch(args);&nbsp; &nbsp; }&nbsp; &nbsp; @SuppressWarnings("unused")&nbsp; &nbsp; private static final Logger LOG = Logger&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .getLogger(TableWithoutCorner.class.getName());}
随时随地看视频慕课网APP

相关分类

Java
我要回答