将选定的行保持在表格视图控件的中间
Posted
技术标签:
【中文标题】将选定的行保持在表格视图控件的中间【英文标题】:Keeping selected row in the middle of a TablView control 【发布时间】:2014-10-03 15:00:09 【问题描述】:无论选择如何变化,我都希望将选定的行保留在 TableView 控件的中间。我必须使用 TableView 上方的按钮(PREV、NEXT)来移动更改选定的行。问题是 TableView 滚动条没有跟随这个选择,所以我需要调用
TableView.scrollTo(int)
保持所选行可见。然而,在调用 scrollTo(int) 后,选定的行最终位于视口的顶部。我想把它放在视口的中间。
这在 Swing 中是可能的,如下所示: http://www.java2s.com/Code/Java/Swing-JFC/ScrollingaCelltotheCenterofaJTableComponent.htm
很遗憾,我无法使用 JavaFX 8 解决此问题。
【问题讨论】:
【参考方案1】:@Jakub 之前在 Java 中建议的调用 show()
方法的示例:
TableViewSkin<?> ts = (TableViewSkin<?>) tableView.getSkin();
VirtualFlow<?> vf = (VirtualFlow<?>) ts.getChildren().get(1);
vf.show(tableView.getSelectionModel().getSelectedIndex())
我还想提请您注意,在此方法之后不建议立即调用tableView
的refresh()
方法。
【讨论】:
【参考方案2】:刚刚为几乎相同的问题找到了更好的解决方案,不幸的是仍然是私有 API,但仅在必要时使用可变行高和滚动。我相信它与按下向上/向下箭头时调用的代码相同。 无需手动计算滚动位置,只需调用 VirtualFlow 的 .show(rowIndex)。
以下代码在 JVM1.8 下工作,它是 Kotlin,但仅在语法上与 Java 不同:
val skin: Skin<*> = tableView.skin
if (skin is SkinBase<*>)
skin.children
.first it is VirtualFlow<*>
.let it as VirtualFlow<*>
.show(rowIndex)
请记住,VirtualFlow 是 Java 9 中的公共 API,因此需要进行一些返工(或者可能只是更改导入)。
【讨论】:
【参考方案3】:这似乎行得通。它使用非公共 API,所以如果有人有更好的解决方案,我仍然很感兴趣。
table.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, newValue) -> Platform.runLater(() ->
TableViewSkin<?> ts = (TableViewSkin<?>) table.getSkin();
VirtualFlow<?> vf = (VirtualFlow<?>)ts.getChildren().get(1);
int first = vf.getFirstVisibleCellWithinViewPort().getIndex();
int last = vf.getLastVisibleCellWithinViewPort().getIndex();
if((newValue.intValue() - ((last - first) / 2)) >= 0)
vf.scrollTo(newValue.intValue() - ((last - first) / 2));
));
限制是所有行必须具有相同的高度。
【讨论】:
以上是关于将选定的行保持在表格视图控件的中间的主要内容,如果未能解决你的问题,请参考以下文章