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

发布于 2024-08-26 18:59:43 字数 426 浏览 8 评论 0 原文

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

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

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

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

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?

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?

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一束光,穿透我孤独的魂 2024-09-02 18:59:43

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

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

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

Fixed Column Table does 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 );
三生路 2024-09-02 18:59:43

JScrollPane 有一个专门用于此目的的区域,即行标题(请参阅 API:)

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

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

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

JScrollPane has an area specifically for this, the row header (see the diagram in the 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.

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.

没有伤那来痛 2024-09-02 18:59:43

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

Check out this class, extracted from 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)
时光礼记 2024-09-02 18:59:43

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文