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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2548139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:43:57  来源:igfitidea点击:

How can I create a JTable where the first column is always in the JScrollPane viewport?

javaswingjtablejscrollpane

提问by voodoogiant

What's the best way to set up a table in a JScrollPane such that the first column is always on the screen in the same position regardless of horizontal scrolling and overlaps columns that pass underneath?

在 JScrollPane 中设置表格的最佳方法是,无论水平滚动如何,第一列始终在屏幕上的同一位置,并与下方通过的列重叠?

When the scrollbar is at the farthest left, the columns look normal, but as the user scrolls to the right, the secondary columns (2 and on) move underneath the first until the last column appears on the far right of the viewport?

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

I found a sample taken from Eckstein's "Java Swing" book that sort of does this, but it doesn't allow resizing of the first column. I was thinking of some scheme where one JPanel held a horizontal struct and a table holding the secondary columns and another JPanel which floated over them (fixed regardless of scrolling). The struct would be to keep the viewport range constant as the first column floated around. Ideally I could do it with two tables using the same model, but I'm not sure if the whole idea is a naive solution.

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

I'd ideally like a setup where multiple tables are on the same scrollpane vertically, where all their first columns are aligned and move together and there are just little horizontal gaps between the individual tables.

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

回答by camickr

Fixed Column Tabledoes most of what you need.

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

It does not support resizing the fixed column so you would need to add code like:

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

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 );

回答by Keilly

JScrollPane has an area specifically for this, the row header (see the diagram in the API:)

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

All you need to do is: - create an extra JTable for this fixed area - hook it up to the first column of your data model - set it as the row header - and in the main table omit or remove the first column of data.

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

When the scrollpane scrolls up and down both tables will scroll in sync with no added code. When the scrollpane scrolls horizontally the row header is always kept visible and only the main table scrolls.

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

For most cases the only added code you'll need is for the column resizing, like camickr's example.

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

回答by George

Check out this class, extracted from http://fahdshariff.blogspot.sg/2010/02/freezing-columns-in-jtable.html

查看这个类,摘自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()); 
    }
}

Thereafter, just call the constructor method:

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

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

回答by DJClayworth

I think you are on the right track. What you conceptually have is a table with a 'header column' for each row. I would use two tables - one has the 'leftmost' column in and the other has all the others. Then I would present these in a JSplitPane with the 'leftmost column' table on the left and the rest on the right. There would be a single vertical scrollbar that controlled the y offset of both tables, and a single horizontal scrollbar controlling the right hand pane (only).

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

You can also use the advanced features of JScrollPane to set a 'header' component on the left of the main scroll area. I've never done it, but you might be able to use that as the 'headers' of your rows.

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