Render table cells

Renderers customize how data is presented. For example, one may customize the rendering of table cells, table column headers, or tree nodes. (IBM has published an excellent article on table renderers and editors.)

To render table cells as desired, first ensure that the table model implements getColumnClass. This will ensure Swing selects the most appropriate default renderer for each column.

If the default renderer is inadequate, then an implementation of TableCellRenderer (which has only one method - getTableCellRendererComponent) must be defined, in one of two ways :

It is important to note that getTableCellRendererComponent : Example 1

The default action of setValue is to place the result of toString into a cell. This value may not be appropriate.

Here, Stock.toString would place unwanted data in the cell. The setValue method is overridden to customize both the text placed in a cell, and its associated tooltip :


package hirondelle.stocks.table;

import javax.swing.table.*;
import hirondelle.stocks.quotes.Stock;
import hirondelle.stocks.util.Util;

/**
* Display a {@link Stock} in a table cell by placing the
* full name in the cell, and by providing its Yahoo ticker 
* (including suffix for the {@link hirondelle.stocks.quotes.Exchange}) as tooltip.
*/
final class RenderStockName extends DefaultTableCellRenderer {
  
  public void setValue(Object aValue) {
    Object result = aValue;
    if ( (aValue != null) && (aValue instanceof Stock) ) {
      Stock stock = (Stock) aValue;
      result = stock.getName();
      StringBuilder tooltip = new StringBuilder("Yahoo Ticker: ");
      tooltip.append(stock.getTicker());
      String suffix = stock.getExchange().getTickerSuffix();
      if ( Util.textHasContent(suffix) ) {
        tooltip.append(".");
        tooltip.append(suffix);
      }
      setToolTipText( tooltip.toString() );
    } 
    super.setValue(result);
  }   
} 


Example 2

Use the current locale to render a Number as a currency :


package hirondelle.stocks.table;

import javax.swing.table.*;
import javax.swing.*;
import java.text.NumberFormat;

/**
* Display a <tt>Number</tt> in a table cell in the format defined by  
* {@link NumberFormat#getCurrencyInstance()}, and aligned to the right.
*/
final class RenderPrice extends DefaultTableCellRenderer {
  
  RenderPrice() { 
    setHorizontalAlignment(SwingConstants.RIGHT);  
  }
  
  public void setValue(Object aValue) {
    Object result = aValue;
    if (( aValue != null) && (aValue instanceof Number)) {
      Number numberValue = (Number)aValue;
      NumberFormat formatter = NumberFormat.getCurrencyInstance();
      result = formatter.format(numberValue.doubleValue());
    } 
    super.setValue(result);
  }   
} 


Example 3

Render as red or green, according to the sign of a Number. The implementation overrides getTableCellRendererComponent instead of setValue, and returns a this reference.


package hirondelle.stocks.table;

import javax.swing.table.*;
import javax.swing.*;
import java.awt.*;

/**
* Display a <tt>Number</tt> in a table cell as either red (for negative values)
* or green (for non-negative values), and aligned on the right.
*
* <P>Note that this class will work with any <tt>Number</tt> -  
* <tt>Double</tt>, <tt>BigDecimal</tt>, etc.
*/
final class RenderRedGreen extends DefaultTableCellRenderer {
  
  RenderRedGreen () {
    setHorizontalAlignment(SwingConstants.RIGHT);   
  }
  
  public Component getTableCellRendererComponent(
    JTable aTable, 
    Object aNumberValue, 
    boolean aIsSelected, 
    boolean aHasFocus, 
    int aRow, int aColumn
  ) {  
    /* 
    * Implementation Note :
    * It is important that no "new" be present in this 
    * implementation (excluding exceptions):
    * if the table is large, then a large number of objects would be 
    * created during rendering.
    */
    if (aNumberValue == null) return this;
    Component renderer = super.getTableCellRendererComponent(
      aTable, aNumberValue, aIsSelected, aHasFocus, aRow, aColumn
    );
    Number value = (Number)aNumberValue;
    if ( value.doubleValue() < 0 ) {
      renderer.setForeground(Color.red);
    }
    else {
      renderer.setForeground(fDarkGreen);
    }
    return this;
  }
  
  // PRIVATE //
  
  //(The default green is too bright and illegible.)
  private Color fDarkGreen = Color.green.darker();
} 

Here is an illustration of all three example renderers :

Illustration of above renderers

See Also :
Indicate table sort
Would you use this technique?
Yes   No   Undecided   
© 2010 Hirondelle Systems | Source Code | Contact | License | Quotes | RSS
Individual code snippets can be used under this BSD license - Last updated on June 5, 2010.
Over 150,000 unique IPs last month - Built with WEB4J.
- In Memoriam : Bill Dirani -