代码之家  ›  专栏  ›  技术社区  ›  voodoogiant

如何创建jtable,其中第一列始终位于jscrollpane视区中?

  •  9
  • voodoogiant  · 技术社区  · 14 年前

    在JScrollPane中设置表的最佳方法是什么?这样,不管水平滚动和重叠下面的列,第一列总是在屏幕上的同一位置?

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

    我找到了一个从埃克斯坦的“JavaSwing”书中获取的样本,它是这样做的,但是它不允许调整第一列的大小。我在考虑一些方案,其中一个jpanel包含一个水平结构,一个表包含第二列,另一个jpanel在它们上面浮动(不管滚动如何,都是固定的)。当第一列四处浮动时,结构将保持视区范围不变。理想情况下,我可以用两个使用相同模型的表来实现,但我不确定整个想法是否是一个幼稚的解决方案。

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

    4 回复  |  直到 6 年前
        1
  •  12
  •   camickr    14 年前

    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 );
    
        2
  •  5
  •   Keilly    14 年前

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

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

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

    在大多数情况下,唯一需要添加的代码是调整列大小,就像camicker的例子一样。

        3
  •  2
  •   George    9 年前

    查看这个类,摘自 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)
    
        4
  •  1
  •   Leigh josh poley    12 年前

    我觉得你走对了。概念上,您拥有的是一个表,其中每一行都有一个“标题列”。我会用两张桌子——一张桌子有最左边的一列,另一张桌子有所有其他的。然后我将在jsplitpane中展示这些内容,其中“最左边的列”表在左边,其余的在右边。将有一个控制两个表的Y偏移量的垂直滚动条和一个控制右侧窗格的水平滚动条(仅)。

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