Add 'count #' column to JTable

Add ‘count #’ column to JTable

Important note first: This is mostly not my code, I was strugling with this problem for some time, I couldn’t google it at all, and one day, I’ve just found it. Now I use it in one of my projects but I cannot find the original post again, therefore I have decided to post it on my blog (slightly modified version of the original) so other people with similar problem will have a better chance of finding the solution.
So, the idea is very simple. The whole point of displaying additional column which is kind of independent from the other columns is to simply use another table. This way you can sort one table by column and the number column will not sort with it. – thats exactly what I was looking for and I guess its kind of popular problem.
Becouse you put two tables in one scroll pane the gui looks like its just one column!


I have created one simple method to apply this technique to any tables in my application (I use JXTable actually but JTable will do as well)

private void addLPColumn(JXTable table, JScrollPane scp){
        JTable rowTable = new RowNumberTable(table);
        scp.setRowHeaderView(rowTable);
        scp.setCorner(JScrollPane.UPPER_LEFT_CORNER, rowTable.getTableHeader());
        scp.repaint();
    }


RowNumberTable is simple one column table displaying the ‘count’ number of rows in the second table.


public class RowNumberTable extends JTable
    implements ChangeListener, PropertyChangeListener
{
    private JTable main;

    public RowNumberTable(JTable table)
    {
        main = table;
        main.addPropertyChangeListener( this );

        setFocusable( false );
        setAutoCreateColumnsFromModel( false );
        setModel( main.getModel() );
        setSelectionModel( main.getSelectionModel() );

        TableColumn column = new TableColumn();
        column.setHeaderValue("Lp.");
        addColumn( column );
        column.setCellRenderer(new RowNumberRenderer());

        getColumnModel().getColumn(0).setPreferredWidth(40);
        setPreferredScrollableViewportSize(getPreferredSize());
    }

    @Override
    public void addNotify()
    {
        super.addNotify();

        Component c = getParent();

        //  Keep scrolling of the row table in sync with the main table.

        if (c instanceof JViewport)
        {
            JViewport viewport = (JViewport)c;
            viewport.addChangeListener( this );
        }
    }

    /*
     *  Delegate method to main table
     */

    @Override
    public int getRowCount()
    {
            if(main != null)
                return main.getRowCount();
            else
                return 0;
    }

    @Override
    public int getRowHeight(int row)
    {
        return main.getRowHeight(row);
    }

    /*
     *  This table does not use any data from the main TableModel,
     *  so just return a value based on the row parameter.
     */

    @Override
    public Object getValueAt(int row, int column)
    {
        return Integer.toString(row + 1);
    }

    /*
     *  Don't edit data in the main TableModel by mistake
     */

    @Override
    public boolean isCellEditable(int row, int column)
    {
        return false;
    }
//
//  Implement the ChangeListener
//
    public void stateChanged(ChangeEvent e)
    {
        //  Keep the scrolling of the row table in sync with main table

        JViewport viewport = (JViewport) e.getSource();
        JScrollPane scrollPane = (JScrollPane)viewport.getParent();
        scrollPane.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
    }
//
//  Implement the PropertyChangeListener
//
    public void propertyChange(PropertyChangeEvent e)
    {
        //  Keep the row table in sync with the main table

        if ("selectionModel".equals(e.getPropertyName()))
        {
            setSelectionModel( main.getSelectionModel() );
        }

        if ("model".equals(e.getPropertyName()))
        {
            setModel( main.getModel() );
        }
    }

    /*
     *  Borrow the renderer from JDK1.4.2 table header
     */

    private static class RowNumberRenderer extends DefaultTableCellRenderer
    {
        public RowNumberRenderer()
        {
            setHorizontalAlignment(JLabel.CENTER);
        }

        public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            if (table != null)
            {
                JTableHeader header = table.getTableHeader();

                if (header != null)
                {
                    setForeground(header.getForeground());
                    setBackground(header.getBackground());
                    setFont(header.getFont());
                }
            }

            if (isSelected)
            {
                setFont( getFont().deriveFont(Font.BOLD) );
            }

            setText((value == null) ? "" : value.toString());
            setBorder(UIManager.getBorder("TableHeader.cellBorder"));

            return this;
        }
    }
}

count_jtable_column

In my case the ‘count’ column is called ‘Lp.’ – in polish



I have created one simple method to apply this technique to any tables in my application (I use JXTable actually but JTable will do as well)

private void addLPColumn(JXTable table, JScrollPane scp){
        JTable rowTable = new RowNumberTable(table);
        scp.setRowHeaderView(rowTable);
        scp.setCorner(JScrollPane.UPPER_LEFT_CORNER, rowTable.getTableHeader());
        scp.repaint();
    }


2 responses on “Add ‘count #’ column to JTable

  1. fernando May 24, 2011 at 3:27 am

    where is the project for download?

  2. admin May 24, 2011 at 8:29 am

    Sorry mate, no project for download here

Leave a Reply