[英]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.