【问题标题】:Keeping selected row in the middle of a TablView control将选定的行保持在表格视图控件的中间
【发布时间】:2025-11-27 21:35:02
【问题描述】:

无论选择如何变化,我都希望将选定的行保留在 TableView 控件的中间。我必须使用 TableView 上方的按钮(PREV、NEXT)来移动更改选定的行。问题是 TableView 滚动条没有跟随这个选择,所以我需要调用

TableView.scrollTo(int)

保持所选行可见。然而,在调用 scrollTo(int) 后,选定的行最终位于视口的顶部。我想把它放在视口的中间。

这在 Swing 中是可能的,如下所示: http://www.java2s.com/Code/Java/Swing-JFC/ScrollingaCelltotheCenterofaJTableComponent.htm

很遗憾,我无法使用 JavaFX 8 解决此问题。

【问题讨论】:

    标签: javafx-8


    【解决方案1】:

    @Jakub 之前在 Java 中建议的调用 show() 方法的示例:

    TableViewSkin<?> ts = (TableViewSkin<?>) tableView.getSkin();
    VirtualFlow<?> vf = (VirtualFlow<?>) ts.getChildren().get(1);
    vf.show(tableView.getSelectionModel().getSelectedIndex())
    

    我还想提请您注意,在此方法之后不建议立即调用tableViewrefresh() 方法。

    【讨论】:

      【解决方案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));
                }
            }));
        

        限制是所有行必须具有相同的高度。

        【讨论】:

          最近更新 更多