在JScrollPane中设置表的最佳方法是什么,这样第一列始终在屏幕上的相同位置,而不管水平滚动和重叠在下面的列?
当滚动条位于最左侧时,列看起来正常,但当用户向右滚动时,辅助列(2和on)在第一列下方移动,直到最后一列出现在视口的最右侧?
我发现了一个取自Eckstein的“Java Swing”书中的样本,但它不允许调整第一列的大小。我在想一些方案,其中一个JPanel持有一个水平结构,一个表保存辅助列,另一个JPanel浮动它们(无论滚动如何都固定)。该结构将保持视口范围不变,因为第一列浮动。理想情况下,我可以使用相同的模型使用两个表,但我不确定整个想法是否是一个天真的解决方案。
我理想地喜欢一种设置,其中多个表在垂直相同的滚动窗格上,其中所有第一列对齐并一起移动,并且各个表之间只有很小的水平间隙。
答案 0 :(得分:12)
Fixed Column Table完成了你需要的大部分工作。
它不支持调整固定列的大小,因此您需要添加如下代码:
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 );
答案 1 :(得分:5)
JScrollPane有一个专门针对此的区域,即行标题(参见API中的图表:)
您需要做的就是: - 为此固定区域创建额外的JTable - 将其连接到数据模型的第一列 - 将其设置为行标题 - 并在主表中省略或删除第一列数据。
当滚动窗格向上和向下滚动时,两个表格将同步滚动而不添加任何代码。当滚动窗格水平滚动时,行标题始终保持可见,只有主表滚动。
对于大多数情况,您需要的唯一添加的代码是列调整大小,如camickr的示例。
答案 2 :(得分:2)
查看此课程,摘自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( <yourData>, <yourColumns> );
FrozenTablePane frozenPane = new FrozenTablePane(table,1);//where 1 is the number of freezed column(s)
答案 3 :(得分:1)
我认为你走在正确的轨道上。您在概念上拥有的是每行包含“标题列”的表。我会使用两个表 - 一个包含“最左边”列,另一个包含所有其他表。然后我会在JSplitPane中显示这些,左边是“最左边的列”表,右边是其余部分。将有一个垂直滚动条控制两个表的y偏移量,一个水平滚动条控制右侧窗格(仅限)。
您还可以使用JScrollPane的高级功能在主滚动区域的左侧设置“标题”组件。我从来没有这样做过,但您可以将其用作行的“标题”。