10

在 JScrollPane 中设置表格的最佳方法是什么,以使第一列始终在屏幕上的同一位置,而不管水平滚动并与下方通过的列重叠?

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

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

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

4

4 回答 4

12

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

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

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 );
于 2010-03-30T21:27:10.830 回答
5

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

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

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

在大多数情况下,您需要的唯一添加代码是调整列大小,如 camickr 的示例。

于 2010-03-30T21:52:13.270 回答
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)
于 2015-03-11T08:17:10.283 回答
1

我认为你在正确的轨道上。从概念上讲,您拥有的是一个表格,每行都有一个“标题列”。我会使用两个表 - 一个包含“最左边”列,另一个包含所有其他列。然后我会在 JSplitPane 中呈现这些,左边是“最左边的列”表,右边是其余的。将有一个控制两个表格的 y 偏移的垂直滚动条,以及一个控制右侧窗格(仅)的水平滚动条。

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

于 2010-03-30T20:10:51.173 回答