Wednesday, February 24, 2010

Freezing columns in a JTable

If you have a really large JTable, you might sometimes want to "freeze" the first column, or the first X columns, so that they do not scroll with the rest of the table. It is quite easy to do so. All you have to do is create a second JTable with the data you want to freeze and use it as the row header view on your scroll pane. I have wrapped this functionality up, in a class called FrozenTablePane to which you provide a JTable and the number of columns to freeze.
/**
 * A ScrollPane which "freezes" the specified number of
 * columns of a JTable.
 *
 * @author fahdshariff
 *
 */
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());
  }
}

2 comments:

  1. Cesar8:25 PM

    Hi Fahd,

    I was trying to use your class example and it works great. The only problem is that i can't get the frozen columns header.

    I mean, i see the 3 columns frozen (without col header) and the rest of the columns scrolleable (just like i wanted it). Am i doing something bad?? why i can't see the frozen column's header??

    Thanks in advance

    ReplyDelete
  2. Hi Fahd,

    Is there anyway I can Freeze first two rows and Columns at the same time ?

    I did come across a number of examples for freezing either rows or columns. I am not sure how to have both in a single table.

    Thank you

    Pradeep

    ReplyDelete