Set the JTable

Choose the color of a JTable cell

September 28, 2001

Q: How can I set the color (or font) on a specific cell (row, column) in a JTable?

A:  In order to set the color or font for a specific table cell you must create a custom TableCellRenderer. The easiest way to create one is to extend the DefaultTableCellRenderer.

Note: Download the example source code that accompanies this article from Resources.

The following custom TableCellRenderer will take a cell that holds an integer and make the cell red if the integer's value is negative.

import java.awt.Component;
import java.awt.Color;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
public class CustomTableCellRenderer extends DefaultTableCellRenderer 
{
    public Component getTableCellRendererComponent
       (JTable table, Object value, boolean isSelected,
       boolean hasFocus, int row, int column) 
    {
        Component cell = super.getTableCellRendererComponent
           (table, value, isSelected, hasFocus, row, column);
        if( value instanceof Integer )
        {
            Integer amount = (Integer) value;
            if( amount.intValue() < 0 )
            {
                cell.setBackground( Color.red );
                // You can also customize the Font and Foreground this way
                // cell.setForeground();
                // cell.setFont();
            }
            else
            {
                cell.setBackground( Color.white );
            }
        }
        return cell;
    }
}

The cell renderer above first checks to make sure it is working with an integer. As a result, the renderer works only for cells that hold an Integer instance (you'll see how to make sure the renderer applies only to integers below). Once the renderer determines that it is working with the proper type, it checks to see if the value is less than zero. If yes, the value is negative and the renderer will render the cell in red. If not, the renderer will render the cell in white. You'll also want to note that you can change the foreground and font as well.

The CustomTableCellRenderer presented above is fairly simple; however, a renderer's logic can be as complicated as you need it to be. getTableCellRendererComponent() is passed the table, the object held in the cell, a boolean indicating whether the cell is selected, a boolean indicating whether the cell has focus, the cell's row, and the cell's column. You can use any combination of these values, or other values already held in the renderer instance, to make your rendering decisions.

Let's put the renderer to work. First, we need a TableModel to hold the data for display:

import javax.swing.table.AbstractTableModel;
public class ExampleTableModel extends AbstractTableModel
{
    private final String[] columnNames = { "Month", "Income" };
    final Object[][] data = {
        {"January",   new Integer(150) },
        {"February",  new Integer(500) },
        {"March",     new Integer(54)  },
        {"April",     new Integer(-50) },
        {"May",       new Integer(52)  },
        {"June",      new Integer(74)  },
        {"July",      new Integer(-25) },
        {"August",    new Integer(62)  },
        {"September", new Integer(15)  },
        {"October",   new Integer(-5)  },
        {"November",  new Integer(5)   },
        {"December",  new Integer(59)  } 
    };
    public Class getColumnClass( int column ) 
    {
        return getValueAt(0, column).getClass();
    }
    public int getColumnCount() 
    {
        return columnNames.length;
    }
    public String getColumnName( int column ) 
    {
        return columnNames[column];
    }
    public int getRowCount() 
    {
        return data.length;
    }
    public Object getValueAt( int row, int column ) 
    {
        return data[row][column];
    }
}

This TableModel holds onto the fictional income of a business over a year. The following main() method creates a table to display the model and use the custom cell renderer presented earlier:

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.table.TableCellRenderer;
import javax.swing.JFrame;
import javax.swing.JTable;
public class TableCellExample 
{
    public static void main( String[] args ) 
    {
        JTable table = new JTable( new ExampleTableModel() ); 
        TableCellRenderer renderer = new CustomTableCellRenderer();
        try
        {
            table.setDefaultRenderer( Class.forName
               ( "java.lang.Integer" ), renderer );
        }
        catch( ClassNotFoundException ex )
        {
            System.exit( 0 );
        }
        JFrame frame = new JFrame();
        frame.addWindowListener( 
            new WindowAdapter() 
            {
                public void windowClosing(WindowEvent e) 
                {
                    System.exit(0);
                }
            }
        );
        frame.getContentPane().add( table );
        frame.pack();
        frame.setVisible( true );
    }
}

The code snippet table.setDefaultRenderer( Class.forName( "java.lang.Integer" ), renderer ); tells the table to use the custom cell renderer for any cell that contains an integer. You can also set a table's renderer by setting the proper TableColumn object directly.

Tony Sintes is an independent consultant and founder of First Class Consulting, Inc., a consulting firm that specializes in the bridging of disparate enterprise systems and training. Outside of First Class Consulting, Tony is an active freelance writer as well as author of Sams Teach Yourself Object-Oriented Programming in 21 Days (Sams, 2001; ISBN: 0672321092).

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more