如何创建JTable,其中第一列始终位于JScrollPane视口中?

在JScrollPane中设置表的最佳方法是什么,使得第一列始终在屏幕上的相同位置,而不管水平滚动和重叠列在下面?

当滚动条位于最左侧时,列看起来正常,但是当用户向右滚动时,辅助列(2和on)在第一列下方移动,直到最后一列出现在视口的最右侧?

我从Eckstein的“Java Swing”一书中找到了一个样本,但是它不允许调整第一列的大小。 我在想一些方案,其中一个JPanel持有一个水平结构,一个表保存辅助列,另一个JPanel浮动在它们上面(无论滚动如何都是固定的)。 结构将是在第一列浮动时保持视口范围不变。 理想情况下,我可以使用相同的模型使用两个表,但我不确定整个想法是否是一个天真的解决方案。

理想情况下,我喜欢一种设置,其中多个表垂直位于同一个滚动窗口上,其中所有第一列都对齐并一起移动,各个表之间只有很小的水平间隙。

固定列表可以满足您的大部分需求。

它不支持调整固定列的大小,因此您需要添加以下代码:

MouseAdapter ma = new MouseAdapter() { TableColumn column; int columnWidth; int pressedX; public void mousePressed(MouseEvent e) { JTableHeader header = (JTableHeader)e.getComponent(); TableColumnModel tcm = header.getColumnModel(); int columnIndex = tcm.getColumnIndexAtX( e.getX() ); Cursor cursor = header.getCursor(); if (columnIndex == tcm.getColumnCount() - 1 && cursor == Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)) { column = tcm.getColumn( columnIndex ); columnWidth = column.getWidth(); pressedX = e.getX(); header.addMouseMotionListener( this ); } } public void mouseReleased(MouseEvent e) { JTableHeader header = (JTableHeader)e.getComponent(); header.removeMouseMotionListener( this ); } public void mouseDragged(MouseEvent e) { int width = columnWidth - pressedX + e.getX(); column.setPreferredWidth( width ); JTableHeader header = (JTableHeader)e.getComponent(); JTable table = header.getTable(); table.setPreferredScrollableViewportSize(table.getPreferredSize()); JScrollPane scrollPane = (JScrollPane)table.getParent().getParent(); scrollPane.revalidate(); } }; JTable fixed = fixedColumnTable.getFixedTable(); fixed.getTableHeader().addMouseListener( ma ); 

JScrollPane有一个专门针对此的区域,即行标题(参见API中的图表:)

您需要做的就是: – 为此固定区域创建额外的JTable – 将其连接到数据模型的第一列 – 将其设置为行标题 – 并在主表中省略或删除第一列数据。

当滚动窗格上下滚动时,两个表将同步滚动而不添加任何代码。 当滚动窗格水平滚动时,行标题始终保持可见,只有主表滚动。

对于大多数情况,您需要的唯一添加的代码是列resize,如camickr的示例。

查看此课程,摘自http://fahdshariff.blogspot.sg/2010/02/freezing-columns-in-jtable.html

 import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JViewport; import javax.swing.table.DefaultTableModel; import javax.swing.table.JTableHeader; import javax.swing.table.TableModel; public class FrozenTablePane extends JScrollPane{ public FrozenTablePane(JTable table, int colsToFreeze){ super(table); TableModel model = table.getModel(); //create a frozen model TableModel frozenModel = new DefaultTableModel( model.getRowCount(), colsToFreeze); //populate the frozen model for (int i = 0; i < model.getRowCount(); i++) { for (int j = 0; j < colsToFreeze; j++) { String value = (String) model.getValueAt(i, j); frozenModel.setValueAt(value, i, j); } } //create frozen table JTable frozenTable = new JTable(frozenModel); //remove the frozen columns from the original table for (int j = 0; j < colsToFreeze; j++) { table.removeColumn(table.getColumnModel().getColumn(0)); } table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); //format the frozen table JTableHeader header = table.getTableHeader(); frozenTable.setBackground(header.getBackground()); frozenTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); frozenTable.setEnabled(false); //set frozen table as row header view JViewport viewport = new JViewport(); viewport.setView(frozenTable); viewport.setPreferredSize(frozenTable.getPreferredSize()); setRowHeaderView(viewport); setCorner(JScrollPane.UPPER_LEFT_CORNER, frozenTable.getTableHeader()); } } 

此后,只需调用构造函数方法:

 JTable table = new JTable( ,  ); FrozenTablePane frozenPane = new FrozenTablePane(table,1);//where 1 is the number of freezed column(s) 

我认为你走在正确的轨道上。 您在概念上拥有的是每行包含“标题列”的表。 我会使用两个表 – 一个包含“最左边”列,另一个包含所有其他表。 然后我会在JSplitPane中显示这些,左边是“最左边的列”表,右边是其余部分。 将有一个垂直滚动条控制两个表的y偏移量,并且一个水平滚动条控制右侧窗格(仅限)。

您还可以使用JScrollPane的高级function在主滚动区域的左侧设置“标题”组件。 我从来没有这样做过,但您可以将其用作行的“标题”。