繁体   English   中英

如何冻结 JTable 中的行

[英]How to freeze rows in JTable

如何冻结JTable行?

这应该与 Microsoft Excel 类似,在 Microsoft Excel 中,用户可以选择一个单元格并右键单击并冻结/解冻行。 我找到了很多关于冻结列而不是行的答案。

谢谢!

简短的回答是,您需要有两个 JScrollPanes:顶部的一个处理冻结的行(带有行标题来处理其冻结的列),底部的一个用于可滚动行(也带有行标题) - 所以你最终得到4张桌子来管理。 不要在顶部滚动窗格中使用滚动条:而是将 ChangeListener 添加到下部滚动窗格 () 的视口中,如下所示:

   public void stateChanged(ChangeEvent e) {
      Point p = spMain.getViewport().getViewPosition();
      p.y = 0;
      spHead.getViewport().setViewPosition(p);
   }

底部窗格的 TableHeader 需要隐藏(至少在显示顶部窗格时):

   spMain.setColumnHeaderView(bodyTable.getTableHeader());
   spMain.getColumnHeader().setVisible(false);

其余的并不是一帆风顺,但如果您没有生成的行号列来模拟 Excel,则可以让您的生活更轻松,不允许冻结已经冻结的表格(您无法在 Excel 中执行此操作) ) 并且不允许排序(至少是冻结部分中的列。我使用的 JVM 有一个“功能”,它使顶部窗格中的标题与下方的列对齐变得复杂,直到顶部表至少有一个行 - 在实际执行“冻结”后仅考虑使用顶部窗格。

一个简单的方法是覆盖表模型的getValueAt()方法。

你可以这样做:

Supplier<Integer> firstVisibleRowIndexSupplier = () -> {
  Point p = scrollPane.getViewport()
                      .getViewPosition();
  return table.rowAtPoint(p);
};

firstVisibleRowIndexSupplier传递给表模型。

在表模型中:

@Override
public Object getValueAt(int row, int column) {
  int firstVisibleRow = this.firstVisibleRowSupplier.get();
  // Logic for returning data for the frozen rows, based on firstVisibleRow
}

缺点是表格在垂直向上滚动时会缓存数据。 一种解决方法是将AdjustmentListener添加到垂直滚动条:

scrollPane.getVerticalScrollBar()
          .addAdjustmentListener(e -> tableModel.refresh());

// TableModel
public void refresh() {
  // Preserves selection
  fireTableChanged(new TableModelEvent(this, //tableModel
    this.firstVisibleRowSupplier.get(), //firstRow
    getRowCount() - 1, //lastRow
    TableModelEvent.ALL_COLUMNS, //column
    TableModelEvent.UPDATE)); //changeType
}

使用此解决方法,有一个我尚未找到修复的小缺点:当用鼠标滚轮向上滚动时,冻结的行将在表更新之前短暂闪烁。 使用滚动条滚动或使用滚动条或鼠标滚轮向下滚动时,这种情况不会发生太多。

暂无
暂无

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

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