正确滚动到 JTable 的选定行

Scroll to selected row correctly for JTable

我正在使用 JTable 来显示数据。当以编程方式选择一行时,它应该(自动)将该行滚动到视图中,使其成为最上面的第一行。为此,我有以下方法:

private static void scrollToSelectedRow(JTable table)
{
    JViewport viewport = (JViewport) table.getParent();
    Rectangle cellRectangle = table.getCellRect(table.getSelectedRow(), 0, true);
    Rectangle visibleRectangle = viewport.getVisibleRect();
    table.scrollRectToVisible(new Rectangle(cellRectangle.x, cellRectangle.y, (int) visibleRectangle.getWidth(), (int) visibleRectangle.getHeight()));
}

问题是调用它可能会或可能不会正确滚动,例如所选行可能以不确定的方式位于顶部或不位于顶部。为了解决这个问题,我尝试调用该方法两次,中间有延迟并重新绘制它:

public static void setSelectedRow(JTable table, int rowIndex, int columnIndex)
{
    table.setRowSelectionInterval(rowIndex, columnIndex);
    scrollToSelectedRow(table);
    try
    {
        Thread.sleep(100);
    } catch (InterruptedException exception)
    {
        exception.printStackTrace();
    }
    scrollToSelectedRow(table);
    table.repaint();
}

这工作得更好,但有时仍然会出现 table 列的故障,因为在更新时停止 EDT 显然是不明智的。 repaint() 调用似乎以类似的方式阻止来自 "overlapping" 的行。通过将鼠标移到受影响的 rows/columns 上可以轻松修复图形故障,但这不应该发生。

如何在不等待且不出现图形故障的情况下优雅地执行滚动?

代码看起来很合理。通常,诀窍是确保 Rectangle width/height 是强制滚动的视口大小。

两个想法。

  1. 去掉 Thread.sleep()。所要做的就是防止 GUI 在 100 毫秒内重新绘制自身。

  2. 尝试将 scrollRectToVisible(...) 包装在 SwingUtlities.invokeLater(...) 中。

如果第 2 点没有帮助,那么 post 证明问题的正确 [mcve]。