Java/Swing Components/Grid Table — различия между версиями

Материал из Java эксперт
Перейти к: навигация, поиск
 
м (1 версия)
 
(нет различий)

Текущая версия на 06:57, 1 июня 2010

Animated Icon Header Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1beta2) */
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.ImageObserver;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
/**
 * @version 1.0 06/19/99
 */
public class AnimatedIconHeaderExample extends JFrame {
  public AnimatedIconHeaderExample() {
    super("AnimatedIconHeader Example");
    final Object[][] data = new Object[][] { { "Leopard", "Lycaon" },
        { "Jagur", "Jackal" }, { "Cheetah", "Coyote" },
        { "Puma", "Dingo" }, { "Lynx", "Fox" }, { "Tom", "Hot" } };
    final String[] column = new String[] { "Cat", "Dog" };
    ImageIcon[] icons = { new ImageIcon("jexpAnimation.gif"),
        new ImageIcon("jexpAnimation.gif") };
    AbstractTableModel model = new AbstractTableModel() {
      public int getColumnCount() {
        return column.length;
      }
      public int getRowCount() {
        return data.length;
      }
      public String getColumnName(int col) {
        return column[col];
      }
      public Object getValueAt(int row, int col) {
        return data[row][col];
      }
    };
    JTable table = new JTable(model);
    JTableHeader header = table.getTableHeader();
    JLabel renderer;
    for (int i = 0; i < model.getColumnCount(); i++) {
      renderer = (JLabel) table.getColumn(column[i]).getHeaderRenderer();
      renderer.setIcon(icons[i]);
      // If you have only one column.
      // icons[i].setImageObserver(header);
      icons[i].setImageObserver(new HeaderImageObserver(header, i));
    }
    JScrollPane pane = new JScrollPane(table);
    getContentPane().add(pane);
  }
  class HeaderImageObserver implements ImageObserver {
    JTableHeader header;
    int col;
    HeaderImageObserver(JTableHeader header, int col) {
      this.header = header;
      this.col = col;
    }
    public boolean imageUpdate(Image img, int flags, int x, int y, int w,
        int h) {
      if ((flags & (FRAMEBITS | ALLBITS)) != 0) {
        Rectangle rect = header.getHeaderRect(col);
        header.repaint(rect);
      }
      return (flags & (ALLBITS | ABORT)) == 0;
    }
  }
  public static void main(String[] args) {
    AnimatedIconHeaderExample frame = new AnimatedIconHeaderExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(300, 140);
    frame.setVisible(true);
  }
}





Animated Icon Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1beta2) */

import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.ImageObserver;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
/**
 * @version 1.0 06/19/99
 */
public class AnimatedIconTableExample extends JFrame {
  public AnimatedIconTableExample() {
    super("AnimatedIconTable Example");
    final Object[][] data = new Object[][] {
        { new ImageIcon("jexpAnimation.gif"),
            new ImageIcon("jexpAnimation.gif") },
        { new ImageIcon("jexpAnimation.gif"),
            new ImageIcon("jexpAnimation.gif") } };
    final Object[] column = new Object[] { "Boy and Girl", "Dog and Cat" };
    AbstractTableModel model = new AbstractTableModel() {
      public int getColumnCount() {
        return column.length;
      }
      public int getRowCount() {
        return data.length;
      }
      public String getColumnName(int col) {
        return (String) column[col];
      }
      public Object getValueAt(int row, int col) {
        return data[row][col];
      }
      public Class getColumnClass(int col) {
        return ImageIcon.class;
      }
    };
    JTable table = new JTable(model);
    table.setRowHeight(50);
    setImageObserver(table);
    JScrollPane pane = new JScrollPane(table);
    getContentPane().add(pane);
  }
  private void setImageObserver(JTable table) {
    TableModel model = table.getModel();
    int colCount = model.getColumnCount();
    int rowCount = model.getRowCount();
    for (int col = 0; col < colCount; col++) {
      if (ImageIcon.class == model.getColumnClass(col)) {
        for (int row = 0; row < rowCount; row++) {
          ImageIcon icon = (ImageIcon) model.getValueAt(row, col);
          if (icon != null) {
            icon.setImageObserver(new CellImageObserver(table, row,
                col));
          }
        }
      }
    }
  }
  class CellImageObserver implements ImageObserver {
    JTable table;
    int row;
    int col;
    CellImageObserver(JTable table, int row, int col) {
      this.table = table;
      this.row = row;
      this.col = col;
    }
    public boolean imageUpdate(Image img, int flags, int x, int y, int w,
        int h) {
      if ((flags & (FRAMEBITS | ALLBITS)) != 0) {
        Rectangle rect = table.getCellRect(row, col, false);
        table.repaint(rect);
      }
      return (flags & (ALLBITS | ABORT)) == 0;
    }
  }
  public static void main(String[] args) {
    AnimatedIconTableExample frame = new AnimatedIconTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}





Button Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.ruponent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
 * @version 1.0 11/09/98
 */
public class JButtonTableExample extends JFrame {
  public JButtonTableExample() {
    super("JButtonTable Example");
    DefaultTableModel dm = new DefaultTableModel();
    dm.setDataVector(new Object[][] { { "button 1", "foo" },
        { "button 2", "bar" } }, new Object[] { "Button", "String" });
    JTable table = new JTable(dm);
    table.getColumn("Button").setCellRenderer(new ButtonRenderer());
    table.getColumn("Button").setCellEditor(
        new ButtonEditor(new JCheckBox()));
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll);
    setSize(400, 100);
    setVisible(true);
  }
  public static void main(String[] args) {
  
   
    JButtonTableExample frame = new JButtonTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
/**
 * @version 1.0 11/09/98
 */
class ButtonRenderer extends JButton implements TableCellRenderer {
  public ButtonRenderer() {
    setOpaque(true);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    if (isSelected) {
      setForeground(table.getSelectionForeground());
      setBackground(table.getSelectionBackground());
    } else {
      setForeground(table.getForeground());
      setBackground(UIManager.getColor("Button.background"));
    }
    setText((value == null) ? "" : value.toString());
    return this;
  }
}
/**
 * @version 1.0 11/09/98
 */
class ButtonEditor extends DefaultCellEditor {
  protected JButton button;
  private String label;
  private boolean isPushed;
  public ButtonEditor(JCheckBox checkBox) {
    super(checkBox);
    button = new JButton();
    button.setOpaque(true);
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        fireEditingStopped();
      }
    });
  }
  public Component getTableCellEditorComponent(JTable table, Object value,
      boolean isSelected, int row, int column) {
    if (isSelected) {
      button.setForeground(table.getSelectionForeground());
      button.setBackground(table.getSelectionBackground());
    } else {
      button.setForeground(table.getForeground());
      button.setBackground(table.getBackground());
    }
    label = (value == null) ? "" : value.toString();
    button.setText(label);
    isPushed = true;
    return button;
  }
  public Object getCellEditorValue() {
    if (isPushed) {
      // 
      // 
      JOptionPane.showMessageDialog(button, label + ": Ouch!");
      // System.out.println(label + ": Ouch!");
    }
    isPushed = false;
    return new String(label);
  }
  public boolean stopCellEditing() {
    isPushed = false;
    return super.stopCellEditing();
  }
  protected void fireEditingStopped() {
    super.fireEditingStopped();
  }
}





Calculated Column Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.ruponent;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class CalculatedColumnTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Calculated Column Table");
    JTable tbl = new JTable(new CurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    // Automatically configure the column widths
    TableUtilities
        .setColumnWidths(tbl, new Insets(0, 4, 0, 4), true, false);
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    // Diagnostics: display the chosen column widths
    for (int i = 0; i < tcm.getColumnCount(); i++) {
      System.out.println("Column " + i + ": width is "
          + tcm.getColumn(i).getPreferredWidth());
    }
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon) value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}
class TableUtilities {
  // Calculate the required width of a table column
  public static int calculateColumnWidth(JTable table, int columnIndex) {
    int width = 0; // The return value
    int rowCount = table.getRowCount();
    for (int i = 0; i < rowCount; i++) {
      TableCellRenderer renderer = table.getCellRenderer(i, columnIndex);
      Component comp = renderer.getTableCellRendererComponent(table,
          table.getValueAt(i, columnIndex), false, false, i,
          columnIndex);
      int thisWidth = comp.getPreferredSize().width;
      if (thisWidth > width) {
        width = thisWidth;
      }
    }
    return width;
  }
  // Set the widths of every column in a table
  public static void setColumnWidths(JTable table, Insets insets,
      boolean setMinimum, boolean setMaximum) {
    int columnCount = table.getColumnCount();
    TableColumnModel tcm = table.getColumnModel();
    int spare = (insets == null ? 0 : insets.left + insets.right);
    for (int i = 0; i < columnCount; i++) {
      int width = calculateColumnWidth(table, i);
      width += spare;
      TableColumn column = tcm.getColumn(i);
      column.setPreferredWidth(width);
      if (setMinimum == true) {
        column.setMinWidth(width);
      }
      if (setMaximum == true) {
        column.setMaxWidth(width);
      }
    }
  }
  // Sort an array of integers in place
  public static void sort(int[] values) {
    int length = values.length;
    if (length > 1) {
      for (int i = 0; i < length - 1; i++) {
        for (int j = i + 1; j < length; j++) {
          if (values[j] < values[i]) {
            int temp = values[i];
            values[i] = values[j];
            values[j] = temp;
          }
        }
      }
    }
  }
}





Cell Border Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
 * @version 1.0 3/06/99
 */
public class CellBorderTableExample extends JFrame {
  public CellBorderTableExample() {
    super("Cell Border Example");
    final Color color = UIManager.getColor("Table.gridColor");
    DefaultTableModel dm = new DefaultTableModel(12, 6) {
      public void setValueAt(Object obj, int row, int col) {
        if (obj instanceof MyData) {
          super.setValueAt(obj, row, col);
        } else {
          MyData myData = null;
          Object oldObject = getValueAt(row, col);
          if (oldObject == null) {
            myData = new MyData(obj, new LinesBorder(color, 0));
          } else if (oldObject instanceof MyData) {
            myData = (MyData) oldObject;
          } else {
            System.out.println("error");
            return;
          }
          myData.setObject(obj);
          super.setValueAt(myData, row, col);
        }
      }
    };
    JTable table = new JTable(dm);
    table.setIntercellSpacing(new Dimension(0, 0));
    table.setCellSelectionEnabled(true);
    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    table.setDefaultRenderer(Object.class, new BorderCellRenderer());
    JScrollPane scroll = new JScrollPane(table);
    ThicknessPanel thicknessPanel = new ThicknessPanel();
    Box box = new Box(BoxLayout.Y_AXIS);
    box.add(thicknessPanel);
    box.add(new ButtonPanel(table, thicknessPanel));
    getContentPane().add(scroll, BorderLayout.CENTER);
    getContentPane().add(box, BorderLayout.EAST);
  }
  public static void main(String[] args) {
    CellBorderTableExample frame = new CellBorderTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(400, 240);
    frame.setVisible(true);
  }
  class ThicknessPanel extends JPanel {
    JComboBox[] combos;
    ThicknessPanel() {
      String[] str = { "top", "left", "bottom", "right" };
      int n = str.length;
      setLayout(new GridLayout(n, 2));
      setBorder(new TitledBorder("Thickness"));
      combos = new JComboBox[n];
      for (int i = 0; i < n; i++) {
        combos[i] = new JComboBox(new Object[] { "0", "1", "2", "3" });
        add(new JLabel(str[i]));
        add(combos[i]);
      }
    }
    public Insets getThickness() {
      Insets insets = new Insets(0, 0, 0, 0);
      insets.top = combos[0].getSelectedIndex();
      insets.left = combos[1].getSelectedIndex();
      insets.bottom = combos[2].getSelectedIndex();
      insets.right = combos[3].getSelectedIndex();
      return insets;
    }
  }
  class ButtonPanel extends JPanel {
    JTable table;
    ThicknessPanel thicknessPanel;
    Color color = UIManager.getColor("Table.gridColor");
    ButtonPanel(JTable table, ThicknessPanel thicknessPanel) {
      this.table = table;
      this.thicknessPanel = thicknessPanel;
      setLayout(new GridLayout(3, 1));
      setBorder(new TitledBorder("Append Lines"));
      final JCheckBox oneBlock = new JCheckBox("Block");
      JButton b_and = new JButton("REPLACE");
      JButton b_or = new JButton("OR");
      add(oneBlock);
      add(b_and);
      add(b_or);
      b_and.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          setCellBorder(true, oneBlock.isSelected());
        }
      });
      b_or.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          setCellBorder(false, oneBlock.isSelected());
        }
      });
    }
    private void setCellBorder(boolean isReplace, boolean isBlock) {
      boolean isTop, isLeft, isBottom, isRight;
      Insets insets = thicknessPanel.getThickness();
      int[] columns = table.getSelectedColumns();
      int[] rows = table.getSelectedRows();
      int rowMax = rows.length;
      int columnMax = columns.length;
      for (int i = 0; i < rowMax; i++) {
        int row = rows[i];
        isTop = (i == 0) ? true : false;
        isBottom = (i == rowMax - 1) ? true : false;
        for (int j = 0; j < columnMax; j++) {
          int column = columns[j];
          isLeft = (j == 0) ? true : false;
          isRight = (j == columnMax - 1) ? true : false;
          MyData myData = (MyData) table.getValueAt(row, column);
          if (myData == null) {
            myData = new MyData("", new LinesBorder(color, 0));
          }
          LinesBorder border = (LinesBorder) myData.getBorder();
          if (isBlock) {
            Insets tmp = new Insets(0, 0, 0, 0);
            if (isTop)
              tmp.top = Math.max(tmp.top, insets.top);
            if (isLeft)
              tmp.left = Math.max(tmp.left, insets.left);
            if (isBottom)
              tmp.bottom = Math.max(tmp.bottom, insets.bottom);
            if (isRight)
              tmp.right = Math.max(tmp.right, insets.right);
            border.append(tmp, isReplace);
          } else {
            border.append(insets, isReplace);
          }
          table.setValueAt(myData, row, column);
        }
      }
      table.clearSelection();
      table.revalidate();
      table.repaint();
    }
  }
  class MyData implements CellBorder {
    private Border border;
    private Object obj;
    public MyData(Object obj, Border border) {
      this.obj = obj;
      this.border = border;
    }
    public void setObject(Object obj) {
      this.obj = obj;
    }
    public String toString() {
      return obj.toString();
    }
    // CellBorder
    public void setBorder(Border border) {
      this.border = border;
    }
    public Border getBorder() {
      return border;
    }
    public void setBorder(Border border, int row, int col) {
    }
    public Border getBorder(int row, int col) {
      return null;
    }
  }
}
class BorderCellRenderer extends JLabel implements TableCellRenderer {
  protected Border noFocusBorder;
  protected Border columnBorder;
  public BorderCellRenderer() {
    noFocusBorder = new EmptyBorder(1, 2, 1, 2);
    setOpaque(true);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    if (isSelected) {
      setForeground(table.getSelectionForeground());
      setBackground(table.getSelectionBackground());
    } else {
      setForeground(table.getForeground());
      setBackground(table.getBackground());
    }
    setFont(table.getFont());
    if (hasFocus) {
      setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      if (table.isCellEditable(row, column)) {
        setForeground(UIManager.getColor("Table.focusCellForeground"));
        setBackground(UIManager.getColor("Table.focusCellBackground"));
      }
    } else {
      if (value instanceof CellBorder) {
        Border border = ((CellBorder) value).getBorder();
        setBorder(border);
      } else {
        if (columnBorder != null) {
          setBorder(columnBorder);
        } else {
          setBorder(noFocusBorder);
        }
      }
    }
    setText((value == null) ? "" : value.toString());
    return this;
  }
  public void setColumnBorder(Border border) {
    columnBorder = border;
  }
  public Border getColumnBorder() {
    return columnBorder;
  }
}
interface CellBorder {
  public Border getBorder();
  public Border getBorder(int row, int column);
  public void setBorder(Border border);
  public void setBorder(Border border, int row, int column);
}
class LinesBorder extends AbstractBorder implements SwingConstants {
  protected int northThickness;
  protected int southThickness;
  protected int eastThickness;
  protected int westThickness;
  protected Color northColor;
  protected Color southColor;
  protected Color eastColor;
  protected Color westColor;
  public LinesBorder(Color color) {
    this(color, 1);
  }
  public LinesBorder(Color color, int thickness) {
    setColor(color);
    setThickness(thickness);
  }
  public LinesBorder(Color color, Insets insets) {
    setColor(color);
    setThickness(insets);
  }
  public void paintBorder(Component c, Graphics g, int x, int y, int width,
      int height) {
    Color oldColor = g.getColor();
    g.setColor(northColor);
    for (int i = 0; i < northThickness; i++) {
      g.drawLine(x, y + i, x + width - 1, y + i);
    }
    g.setColor(southColor);
    for (int i = 0; i < southThickness; i++) {
      g
          .drawLine(x, y + height - i - 1, x + width - 1, y + height
              - i - 1);
    }
    g.setColor(eastColor);
    for (int i = 0; i < westThickness; i++) {
      g.drawLine(x + i, y, x + i, y + height - 1);
    }
    g.setColor(westColor);
    for (int i = 0; i < eastThickness; i++) {
      g.drawLine(x + width - i - 1, y, x + width - i - 1, y + height - 1);
    }
    g.setColor(oldColor);
  }
  public Insets getBorderInsets(Component c) {
    return new Insets(northThickness, westThickness, southThickness,
        eastThickness);
  }
  public Insets getBorderInsets(Component c, Insets insets) {
    return new Insets(northThickness, westThickness, southThickness,
        eastThickness);
  }
  public boolean isBorderOpaque() {
    return true;
  }
  public void setColor(Color c) {
    northColor = c;
    southColor = c;
    eastColor = c;
    westColor = c;
  }
  public void setColor(Color c, int direction) {
    switch (direction) {
    case NORTH:
      northColor = c;
      break;
    case SOUTH:
      southColor = c;
      break;
    case EAST:
      eastColor = c;
      break;
    case WEST:
      westColor = c;
      break;
    default:
    }
  }
  public void setThickness(int n) {
    northThickness = n;
    southThickness = n;
    eastThickness = n;
    westThickness = n;
  }
  public void setThickness(Insets insets) {
    northThickness = insets.top;
    southThickness = insets.bottom;
    eastThickness = insets.right;
    westThickness = insets.left;
  }
  public void setThickness(int n, int direction) {
    switch (direction) {
    case NORTH:
      northThickness = n;
      break;
    case SOUTH:
      southThickness = n;
      break;
    case EAST:
      eastThickness = n;
      break;
    case WEST:
      westThickness = n;
      break;
    default:
    }
  }
  public void append(LinesBorder b, boolean isReplace) {
    if (isReplace) {
      northThickness = b.northThickness;
      southThickness = b.southThickness;
      eastThickness = b.eastThickness;
      westThickness = b.westThickness;
    } else {
      northThickness = Math.max(northThickness, b.northThickness);
      southThickness = Math.max(southThickness, b.southThickness);
      eastThickness = Math.max(eastThickness, b.eastThickness);
      westThickness = Math.max(westThickness, b.westThickness);
    }
  }
  public void append(Insets insets, boolean isReplace) {
    if (isReplace) {
      northThickness = insets.top;
      southThickness = insets.bottom;
      eastThickness = insets.right;
      westThickness = insets.left;
    } else {
      northThickness = Math.max(northThickness, insets.top);
      southThickness = Math.max(southThickness, insets.bottom);
      eastThickness = Math.max(eastThickness, insets.right);
      westThickness = Math.max(westThickness, insets.left);
    }
  }
}





Colored Cell Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
 * (swing1.1beta3)
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
/**
 * @version 1.0 11/22/98
 */
public class ColoredCellTableExample extends JFrame {
  private JTable table;
  private ColoredCell cellAtt;
  public ColoredCellTableExample() {
    super("Colored Cell Example");
    AttributiveCellTableModel ml = new AttributiveCellTableModel(10, 6);
    cellAtt = (ColoredCell) ml.getCellAttribute();
    table = new JTable(ml);
    table.setCellSelectionEnabled(true);
    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    table.setDefaultRenderer(Object.class, new AttributiveCellRenderer());
    JScrollPane scroll = new JScrollPane(table);
    JButton b_fore = new JButton("Foreground");
    b_fore.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        changeColor(true);
      }
    });
    JButton b_back = new JButton("Background");
    b_back.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        changeColor(false);
      }
    });
    JPanel p_buttons = new JPanel();
    p_buttons.setLayout(new GridLayout(2, 1));
    p_buttons.add(b_fore);
    p_buttons.add(b_back);
    Box box = new Box(BoxLayout.X_AXIS);
    box.add(scroll);
    box.add(new JSeparator(SwingConstants.HORIZONTAL));
    box.add(p_buttons);
    getContentPane().add(box);
    setSize(400, 200);
    setVisible(true);
  }
  private final void changeColor(boolean isForeground) {
    int[] columns = table.getSelectedColumns();
    int[] rows = table.getSelectedRows();
    if ((rows == null) || (columns == null))
      return;
    if ((rows.length < 1) || (columns.length < 1))
      return;
    Color target = cellAtt.getForeground(rows[0], columns[0]);
    Color reference = cellAtt.getBackground(rows[0], columns[0]);
    for (int i = 0; i < rows.length; i++) {
      int row = rows[i];
      for (int j = 0; j < columns.length; j++) {
        int column = columns[j];
        target = (target != cellAtt.getForeground(row, column)) ? null
            : target;
        reference = (reference != cellAtt.getBackground(row, column)) ? null
            : reference;
      }
    }
    String title;
    if (isForeground) {
      target = (target != null) ? target : table.getForeground();
      reference = (reference != null) ? reference : table.getBackground();
      title = "Foreground Color";
    } else {
      target = (reference != null) ? reference : table.getBackground();
      reference = (target != null) ? target : table.getForeground();
      title = "Foreground Color";
    }
    TextColorChooser chooser = new TextColorChooser(target, reference,
        isForeground);
    Color color = chooser.showDialog(ColoredCellTableExample.this, title);
    if (color != null) {
      if (isForeground) {
        cellAtt.setForeground(color, rows, columns);
      } else {
        cellAtt.setBackground(color, rows, columns);
      }
      table.clearSelection();
      table.revalidate();
      table.repaint();
    }
  }
  public static void main(String[] args) {
    ColoredCellTableExample frame = new ColoredCellTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
/*
 * (swing1.1beta3)
 *  
 */
/**
 * @version 1.0 11/22/98
 */
class AttributiveCellTableModel extends DefaultTableModel {
  protected CellAttribute cellAtt;
  public AttributiveCellTableModel() {
    this((Vector) null, 0);
  }
  public AttributiveCellTableModel(int numRows, int numColumns) {
    Vector names = new Vector(numColumns);
    names.setSize(numColumns);
    setColumnIdentifiers(names);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows, numColumns);
  }
  public AttributiveCellTableModel(Vector columnNames, int numRows) {
    setColumnIdentifiers(columnNames);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
  }
  public AttributiveCellTableModel(Object[] columnNames, int numRows) {
    this(convertToVector(columnNames), numRows);
  }
  public AttributiveCellTableModel(Vector data, Vector columnNames) {
    setDataVector(data, columnNames);
  }
  public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
    setDataVector(data, columnNames);
  }
  public void setDataVector(Vector newData, Vector columnNames) {
    if (newData == null)
      throw new IllegalArgumentException("setDataVector() - Null parameter");
    dataVector = new Vector(0);
    setColumnIdentifiers(columnNames);
    dataVector = newData;
    //
    cellAtt = new DefaultCellAttribute(dataVector.size(), columnIdentifiers
        .size());
    newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public void addColumn(Object columnName, Vector columnData) {
    if (columnName == null)
      throw new IllegalArgumentException("addColumn() - null parameter");
    columnIdentifiers.addElement(columnName);
    int index = 0;
    Enumeration eeration = dataVector.elements();
    while (eeration.hasMoreElements()) {
      Object value;
      if ((columnData != null) && (index < columnData.size()))
        value = columnData.elementAt(index);
      else
        value = null;
      ((Vector) eeration.nextElement()).addElement(value);
      index++;
    }
    //
    cellAtt.addColumn();
    fireTableStructureChanged();
  }
  public void addRow(Vector rowData) {
    Vector newData = null;
    if (rowData == null) {
      newData = new Vector(getColumnCount());
    } else {
      rowData.setSize(getColumnCount());
    }
    dataVector.addElement(newData);
    //
    cellAtt.addRow();
    newRowsAdded(new TableModelEvent(this, getRowCount() - 1,
        getRowCount() - 1, TableModelEvent.ALL_COLUMNS,
        TableModelEvent.INSERT));
  }
  public void insertRow(int row, Vector rowData) {
    if (rowData == null) {
      rowData = new Vector(getColumnCount());
    } else {
      rowData.setSize(getColumnCount());
    }
    dataVector.insertElementAt(rowData, row);
    //
    cellAtt.insertRow(row);
    newRowsAdded(new TableModelEvent(this, row, row,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public CellAttribute getCellAttribute() {
    return cellAtt;
  }
  public void setCellAttribute(CellAttribute newCellAtt) {
    int numColumns = getColumnCount();
    int numRows = getRowCount();
    if ((newCellAtt.getSize().width != numColumns)
        || (newCellAtt.getSize().height != numRows)) {
      newCellAtt.setSize(new Dimension(numRows, numColumns));
    }
    cellAtt = newCellAtt;
    fireTableDataChanged();
  }
  /*
   * public void changeCellAttribute(int row, int column, Object command) {
   * cellAtt.changeAttribute(row, column, command); }
   * 
   * public void changeCellAttribute(int[] rows, int[] columns, Object
   * command) { cellAtt.changeAttribute(rows, columns, command); }
   */
}
/**
 * @version 1.0 11/22/98
 */
class DefaultCellAttribute
//    implements CellAttribute ,CellSpan {
    implements CellAttribute, CellSpan, ColoredCell, CellFont {
  //
  // !!!! CAUTION !!!!!
  // these values must be synchronized to Table data
  //
  protected int rowSize;
  protected int columnSize;
  protected int[][][] span; // CellSpan
  protected Color[][] foreground; // ColoredCell
  protected Color[][] background; //
  protected Font[][] font; // CellFont
  public DefaultCellAttribute() {
    this(1, 1);
  }
  public DefaultCellAttribute(int numRows, int numColumns) {
    setSize(new Dimension(numColumns, numRows));
  }
  protected void initValue() {
    for (int i = 0; i < span.length; i++) {
      for (int j = 0; j < span[i].length; j++) {
        span[i][j][CellSpan.COLUMN] = 1;
        span[i][j][CellSpan.ROW] = 1;
      }
    }
  }
  //
  // CellSpan
  //
  public int[] getSpan(int row, int column) {
    if (isOutOfBounds(row, column)) {
      int[] ret_code = { 1, 1 };
      return ret_code;
    }
    return span[row][column];
  }
  public void setSpan(int[] span, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    this.span[row][column] = span;
  }
  public boolean isVisible(int row, int column) {
    if (isOutOfBounds(row, column))
      return false;
    if ((span[row][column][CellSpan.COLUMN] < 1)
        || (span[row][column][CellSpan.ROW] < 1))
      return false;
    return true;
  }
  public void combine(int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    int rowSpan = rows.length;
    int columnSpan = columns.length;
    int startRow = rows[0];
    int startColumn = columns[0];
    for (int i = 0; i < rowSpan; i++) {
      for (int j = 0; j < columnSpan; j++) {
        if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
            || (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
          //System.out.println("can"t combine");
          return;
        }
      }
    }
    for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
      for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
        span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
        span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
        //System.out.println("r " +ii +" c " +jj);
      }
    }
    span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
    span[startRow][startColumn][CellSpan.ROW] = rowSpan;
  }
  public void split(int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    int columnSpan = span[row][column][CellSpan.COLUMN];
    int rowSpan = span[row][column][CellSpan.ROW];
    for (int i = 0; i < rowSpan; i++) {
      for (int j = 0; j < columnSpan; j++) {
        span[row + i][column + j][CellSpan.COLUMN] = 1;
        span[row + i][column + j][CellSpan.ROW] = 1;
      }
    }
  }
  //
  // ColoredCell
  //
  public Color getForeground(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return foreground[row][column];
  }
  public void setForeground(Color color, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    foreground[row][column] = color;
  }
  public void setForeground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(foreground, color, rows, columns);
  }
  public Color getBackground(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return background[row][column];
  }
  public void setBackground(Color color, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    background[row][column] = color;
  }
  public void setBackground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(background, color, rows, columns);
  }
  //
  //
  // CellFont
  //
  public Font getFont(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return font[row][column];
  }
  public void setFont(Font font, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    this.font[row][column] = font;
  }
  public void setFont(Font font, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(this.font, font, rows, columns);
  }
  //
  //
  // CellAttribute
  //
  public void addColumn() {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows][numColumns + 1][2];
    System.arraycopy(oldSpan, 0, span, 0, numRows);
    for (int i = 0; i < numRows; i++) {
      span[i][numColumns][CellSpan.COLUMN] = 1;
      span[i][numColumns][CellSpan.ROW] = 1;
    }
  }
  public void addRow() {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    System.arraycopy(oldSpan, 0, span, 0, numRows);
    for (int i = 0; i < numColumns; i++) {
      span[numRows][i][CellSpan.COLUMN] = 1;
      span[numRows][i][CellSpan.ROW] = 1;
    }
  }
  public void insertRow(int row) {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    if (0 < row) {
      System.arraycopy(oldSpan, 0, span, 0, row - 1);
    }
    System.arraycopy(oldSpan, 0, span, row, numRows - row);
    for (int i = 0; i < numColumns; i++) {
      span[row][i][CellSpan.COLUMN] = 1;
      span[row][i][CellSpan.ROW] = 1;
    }
  }
  public Dimension getSize() {
    return new Dimension(rowSize, columnSize);
  }
  public void setSize(Dimension size) {
    columnSize = size.width;
    rowSize = size.height;
    span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
    foreground = new Color[rowSize][columnSize];
    background = new Color[rowSize][columnSize];
    font = new Font[rowSize][columnSize];
    initValue();
  }
  /*
   * public void changeAttribute(int row, int column, Object command) { }
   * 
   * public void changeAttribute(int[] rows, int[] columns, Object command) { }
   */
  protected boolean isOutOfBounds(int row, int column) {
    if ((row < 0) || (rowSize <= row) || (column < 0)
        || (columnSize <= column)) {
      return true;
    }
    return false;
  }
  protected boolean isOutOfBounds(int[] rows, int[] columns) {
    for (int i = 0; i < rows.length; i++) {
      if ((rows[i] < 0) || (rowSize <= rows[i]))
        return true;
    }
    for (int i = 0; i < columns.length; i++) {
      if ((columns[i] < 0) || (columnSize <= columns[i]))
        return true;
    }
    return false;
  }
  protected void setValues(Object[][] target, Object value, int[] rows,
      int[] columns) {
    for (int i = 0; i < rows.length; i++) {
      int row = rows[i];
      for (int j = 0; j < columns.length; j++) {
        int column = columns[j];
        target[row][column] = value;
      }
    }
  }
}
/**
 * @version 1.0 11/22/98
 */
/*
 * (swing1.1beta3)
 *  
 */
/**
 * @version 1.0 11/22/98
 */
interface CellAttribute {
  public void addColumn();
  public void addRow();
  public void insertRow(int row);
  public Dimension getSize();
  public void setSize(Dimension size);
}
interface ColoredCell {
  public Color getForeground(int row, int column);
  public void setForeground(Color color, int row, int column);
  public void setForeground(Color color, int[] rows, int[] columns);
  public Color getBackground(int row, int column);
  public void setBackground(Color color, int row, int column);
  public void setBackground(Color color, int[] rows, int[] columns);
}
/**
 * @version 1.0 11/22/98
 */
class AttributiveCellRenderer extends JLabel implements TableCellRenderer {
  protected static Border noFocusBorder;
  public AttributiveCellRenderer() {
    noFocusBorder = new EmptyBorder(1, 2, 1, 2);
    setOpaque(true);
    setBorder(noFocusBorder);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    Color foreground = null;
    Color background = null;
    Font font = null;
    TableModel model = table.getModel();
    if (model instanceof AttributiveCellTableModel) {
      CellAttribute cellAtt = ((AttributiveCellTableModel) model)
          .getCellAttribute();
      if (cellAtt instanceof ColoredCell) {
        foreground = ((ColoredCell) cellAtt).getForeground(row, column);
        background = ((ColoredCell) cellAtt).getBackground(row, column);
      }
      if (cellAtt instanceof CellFont) {
        font = ((CellFont) cellAtt).getFont(row, column);
      }
    }
    if (isSelected) {
      setForeground((foreground != null) ? foreground : table
          .getSelectionForeground());
      setBackground(table.getSelectionBackground());
    } else {
      setForeground((foreground != null) ? foreground : table
          .getForeground());
      setBackground((background != null) ? background : table
          .getBackground());
    }
    setFont((font != null) ? font : table.getFont());
    if (hasFocus) {
      setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      if (table.isCellEditable(row, column)) {
        setForeground((foreground != null) ? foreground : UIManager
            .getColor("Table.focusCellForeground"));
        setBackground(UIManager.getColor("Table.focusCellBackground"));
      }
    } else {
      setBorder(noFocusBorder);
    }
    setValue(value);
    return this;
  }
  protected void setValue(Object value) {
    setText((value == null) ? "" : value.toString());
  }
}
/**
 * @version 1.0 11/22/98
 */
class TextPreviewLabel extends JLabel {
  private String sampleText = "  Sample Text  Sample Text  ";
  boolean isForgroundSelection;
  public TextPreviewLabel() {
    this(Color.black, Color.white, true);
  }
  public TextPreviewLabel(Color fore, Color back, boolean isForgroundSelection) {
    setOpaque(true);
    setForeground(fore);
    setBackground(back);
    this.isForgroundSelection = isForgroundSelection;
    setText(sampleText);
  }
  public void setForeground(Color col) {
    if (isForgroundSelection) {
      super.setForeground(col);
    } else {
      super.setBackground(col);
    }
  }
}
class ColorChooserDialog extends JDialog {
  private Color initialColor;
  private Color retColor;
  private JColorChooser chooserPane;
  public ColorChooserDialog(Component c, String title,
      final JColorChooser chooserPane) {
    super(JOptionPane.getFrameForComponent(c), title, true);
    setResizable(false);
    this.chooserPane = chooserPane;
    String okString = UIManager.getString("ColorChooser.okText");
    String cancelString = UIManager.getString("ColorChooser.cancelText");
    String resetString = UIManager.getString("ColorChooser.resetText");
    Container contentPane = getContentPane();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(chooserPane, BorderLayout.CENTER);
    JPanel buttonPane = new JPanel();
    buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
    JButton okButton = new JButton(okString);
    getRootPane().setDefaultButton(okButton);
    okButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        retColor = chooserPane.getColor();
        setVisible(false);
      }
    });
    buttonPane.add(okButton);
    JButton cancelButton = new JButton(cancelString);
    cancelButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        retColor = null;
        setVisible(false);
      }
    });
    buttonPane.add(cancelButton);
    JButton resetButton = new JButton(resetString);
    resetButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chooserPane.setColor(initialColor);
      }
    });
    buttonPane.add(resetButton);
    contentPane.add(buttonPane, BorderLayout.SOUTH);
    pack();
    setLocationRelativeTo(c);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        setVisible(false);
      }
    });
  }
  public Color getColor() {
    return retColor;
  }
}
class TextColorChooser extends JColorChooser {
  public TextColorChooser(Color target, Color reference,
      boolean isForgroundSelection) {
    super(target);
    if (isForgroundSelection) {
      setPreviewPanel(new TextPreviewLabel(target, reference,
          isForgroundSelection));
    } else {
      setPreviewPanel(new TextPreviewLabel(reference, target,
          isForgroundSelection));
    }
    updateUI();
  }
  public Color showDialog(Component component, String title) {
    ColorChooserDialog dialog = new ColorChooserDialog(component, title,
        this);
    dialog.show();
    Color col = dialog.getColor();
    dialog.dispose();
    return col;
  }
}
interface CellFont {
  public Font getFont(int row, int column);
  public void setFont(Font font, int row, int column);
  public void setFont(Font font, int[] rows, int[] columns);
}
interface CellSpan {
  public final int ROW = 0;
  public final int COLUMN = 1;
  public int[] getSpan(int row, int column);
  public void setSpan(int[] span, int row, int column);
  public boolean isVisible(int row, int column);
  public void combine(int[] rows, int[] columns);
  public void split(int row, int column);
}





Column Border Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
/**
 * @version 1.0 3/06/99
 */
public class ColumnBorderTableExample extends JFrame {
  public ColumnBorderTableExample() {
    super("Column Border Example");
    DefaultTableModel dm = new DefaultTableModel(4, 10);
    JTable table = new JTable(dm);
    table.setIntercellSpacing(new Dimension(0, 0));
    Color color = table.getGridColor();
    BorderCellRenderer[] renderers = new BorderCellRenderer[6];
    renderers[0] = createRenderer(color, new Insets(0, 0, 0, 1));
    renderers[1] = createRenderer(color, new Insets(0, 1, 0, 1));
    renderers[2] = createRenderer(color, new Insets(0, 1, 0, 2));
    renderers[3] = createRenderer(color, new Insets(0, 2, 0, 2));
    renderers[4] = createRenderer(color, new Insets(0, 2, 0, 0));
    renderers[5] = createRenderer(Color.red, new Insets(0, 1, 1, 1));
    TableColumnModel model = table.getColumnModel();
    model.getColumn(1).setCellRenderer(renderers[0]);
    model.getColumn(2).setCellRenderer(renderers[0]);
    model.getColumn(3).setCellRenderer(renderers[0]);
    model.getColumn(4).setCellRenderer(renderers[1]);
    model.getColumn(5).setCellRenderer(renderers[2]);
    model.getColumn(6).setCellRenderer(renderers[3]);
    model.getColumn(7).setCellRenderer(renderers[4]);
    model.getColumn(8).setCellRenderer(renderers[5]);
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll, BorderLayout.CENTER);
  }
  public static void main(String[] args) {
    ColumnBorderTableExample frame = new ColumnBorderTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(300, 120);
    frame.setVisible(true);
  }
  private static BorderCellRenderer createRenderer(Color color, Insets insets) {
    BorderCellRenderer renderer = new BorderCellRenderer();
    renderer.setColumnBorder(new LinesBorder(color, insets));
    return renderer;
  }
}
class BorderCellRenderer extends JLabel implements TableCellRenderer {
  protected Border noFocusBorder;
  protected Border columnBorder;
  public BorderCellRenderer() {
    noFocusBorder = new EmptyBorder(1, 2, 1, 2);
    setOpaque(true);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    if (isSelected) {
      setForeground(table.getSelectionForeground());
      setBackground(table.getSelectionBackground());
    } else {
      setForeground(table.getForeground());
      setBackground(table.getBackground());
    }
    setFont(table.getFont());
    if (hasFocus) {
      setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      if (table.isCellEditable(row, column)) {
        setForeground(UIManager.getColor("Table.focusCellForeground"));
        setBackground(UIManager.getColor("Table.focusCellBackground"));
      }
    } else {
      if (value instanceof CellBorder) {
        Border border = ((CellBorder) value).getBorder();
        setBorder(border);
      } else {
        if (columnBorder != null) {
          setBorder(columnBorder);
        } else {
          setBorder(noFocusBorder);
        }
      }
    }
    setText((value == null) ? "" : value.toString());
    return this;
  }
  public void setColumnBorder(Border border) {
    columnBorder = border;
  }
  public Border getColumnBorder() {
    return columnBorder;
  }
}
interface CellBorder {
  public Border getBorder();
  public Border getBorder(int row, int column);
  public void setBorder(Border border);
  public void setBorder(Border border, int row, int column);
}
class LinesBorder extends AbstractBorder implements SwingConstants {
  protected int northThickness;
  protected int southThickness;
  protected int eastThickness;
  protected int westThickness;
  protected Color northColor;
  protected Color southColor;
  protected Color eastColor;
  protected Color westColor;
  public LinesBorder(Color color) {
    this(color, 1);
  }
  public LinesBorder(Color color, int thickness) {
    setColor(color);
    setThickness(thickness);
  }
  public LinesBorder(Color color, Insets insets) {
    setColor(color);
    setThickness(insets);
  }
  public void paintBorder(Component c, Graphics g, int x, int y, int width,
      int height) {
    Color oldColor = g.getColor();
    g.setColor(northColor);
    for (int i = 0; i < northThickness; i++) {
      g.drawLine(x, y + i, x + width - 1, y + i);
    }
    g.setColor(southColor);
    for (int i = 0; i < southThickness; i++) {
      g
          .drawLine(x, y + height - i - 1, x + width - 1, y + height
              - i - 1);
    }
    g.setColor(eastColor);
    for (int i = 0; i < westThickness; i++) {
      g.drawLine(x + i, y, x + i, y + height - 1);
    }
    g.setColor(westColor);
    for (int i = 0; i < eastThickness; i++) {
      g.drawLine(x + width - i - 1, y, x + width - i - 1, y + height - 1);
    }
    g.setColor(oldColor);
  }
  public Insets getBorderInsets(Component c) {
    return new Insets(northThickness, westThickness, southThickness,
        eastThickness);
  }
  public Insets getBorderInsets(Component c, Insets insets) {
    return new Insets(northThickness, westThickness, southThickness,
        eastThickness);
  }
  public boolean isBorderOpaque() {
    return true;
  }
  public void setColor(Color c) {
    northColor = c;
    southColor = c;
    eastColor = c;
    westColor = c;
  }
  public void setColor(Color c, int direction) {
    switch (direction) {
    case NORTH:
      northColor = c;
      break;
    case SOUTH:
      southColor = c;
      break;
    case EAST:
      eastColor = c;
      break;
    case WEST:
      westColor = c;
      break;
    default:
    }
  }
  public void setThickness(int n) {
    northThickness = n;
    southThickness = n;
    eastThickness = n;
    westThickness = n;
  }
  public void setThickness(Insets insets) {
    northThickness = insets.top;
    southThickness = insets.bottom;
    eastThickness = insets.right;
    westThickness = insets.left;
  }
  public void setThickness(int n, int direction) {
    switch (direction) {
    case NORTH:
      northThickness = n;
      break;
    case SOUTH:
      southThickness = n;
      break;
    case EAST:
      eastThickness = n;
      break;
    case WEST:
      westThickness = n;
      break;
    default:
    }
  }
  public void append(LinesBorder b, boolean isReplace) {
    if (isReplace) {
      northThickness = b.northThickness;
      southThickness = b.southThickness;
      eastThickness = b.eastThickness;
      westThickness = b.westThickness;
    } else {
      northThickness = Math.max(northThickness, b.northThickness);
      southThickness = Math.max(southThickness, b.southThickness);
      eastThickness = Math.max(eastThickness, b.eastThickness);
      westThickness = Math.max(westThickness, b.westThickness);
    }
  }
  public void append(Insets insets, boolean isReplace) {
    if (isReplace) {
      northThickness = insets.top;
      southThickness = insets.bottom;
      eastThickness = insets.right;
      westThickness = insets.left;
    } else {
      northThickness = Math.max(northThickness, insets.top);
      southThickness = Math.max(southThickness, insets.bottom);
      eastThickness = Math.max(eastThickness, insets.right);
      westThickness = Math.max(westThickness, insets.left);
    }
  }
}





Column popup menu

 
(From http://swinglabs.org/downloads.jsp)





ComboBox Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import javax.swing.*;
import javax.swing.table.*;
import java.awt.event.*;
public class ComboBoxTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Combo Box Table");
    JTable tbl = new JTable(new ComboBoxTableModel());
    
    // Create the combo box editor
    JComboBox comboBox = new JComboBox(ComboBoxTableModel.getValidStates());
    comboBox.setEditable(true);
    DefaultCellEditor editor = new DefaultCellEditor(comboBox);
    // Assign the editor to the second column
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(1).setCellEditor(editor);
    // Set column widths
    tcm.getColumn(0).setPreferredWidth(200);
    tcm.getColumn(1).setPreferredWidth(100);
    // Set row heighht
    tbl.setRowHeight(20);
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());  
    f.getContentPane().add(new JScrollPane(tbl), "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class ComboBoxTableModel extends AbstractTableModel {
  // Implementation of TableModel interface 
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  public boolean isCellEditable(int row, int column) {
    return column == 1;
  }
  public void setValueAt(Object value, int row, int column) {
    if (isValidValue(value)) {
      data[row][column] = value;
      fireTableRowsUpdated(row, row);
    }
  }
  // Extra public methods
  public static String[] getValidStates() {
    return validStates;
  }
  // Protected methods
  protected boolean isValidValue(Object value) {
    if (value instanceof String) {
      String sValue = (String)value;
      for (int i = 0; i < validStates.length; i++) {
        if (sValue.equals(validStates[i])) {
          return true;
        }
      }
    }
    return false;
  }
  protected static final int COLUMN_COUNT = 2;
    
  protected static final String[] validStates = { 
    "On order", "In stock", "Out of print"
  };
  protected Object[][] data = new Object[][] {
    { "Core Java Volume 1", validStates[0] },
    { "Core Java Volume 2", validStates[0] },
    { "Core Web Programming", validStates[0] },
    { "Core Visual Basic 5", validStates[0] },
    { "Core Java Foundation Classes", validStates[0] }
  };
  
  protected static final String[] columnNames = {
    "Book Name", "Status"
  };
}





CurrencyTable

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumnModel;
public class CurrencyTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Currency Table");
    JTable tbl = new JTable(new CurrencyTableModel());
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}





Each Row with different Editor Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1) */

import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.event.ruponentAdapter;
import java.awt.event.ruponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import java.util.Hashtable;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
/**
 * @version 1.1 09/09/99
 */
public class EachRowEditorExample extends JFrame {
  public EachRowEditorExample() {
    super("EachRow Editor Example");
    DefaultTableModel dm = new DefaultTableModel();
    dm.setDataVector(new Object[][] { { "Name", "MyName" },
        { "Gender", "Male" } }, new Object[] { "Column1", "Column2" });
    JTable table = new JTable(dm);
    JComboBox comboBox = new JComboBox();
    comboBox.addItem("Male");
    comboBox.addItem("Female");
    comboBox.addComponentListener(new ComponentAdapter() {
      public void componentShown(ComponentEvent e) {
        final JComponent c = (JComponent) e.getSource();
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            c.requestFocus();
            System.out.println(c);
            if (c instanceof JComboBox) {
              System.out.println("a");
            }
          }
        });
      }
    });
    EachRowEditor rowEditor = new EachRowEditor(table);
    rowEditor.setEditorAt(1, new DefaultCellEditor(comboBox));
    table.getColumn("Column2").setCellEditor(rowEditor);
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll, BorderLayout.CENTER);
    setSize(400, 100);
    setVisible(true);
  }
  public static void main(String[] args) {
    EachRowEditorExample frame = new EachRowEditorExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
/**
 * each row TableCellEditor
 * 
 * @version 1.1 09/09/99
 * @author Nobuo Tamemasa
 */
class EachRowEditor implements TableCellEditor {
  protected Hashtable editors;
  protected TableCellEditor editor, defaultEditor;
  JTable table;
  /**
   * Constructs a EachRowEditor. create default editor
   * 
   * @see TableCellEditor
   * @see DefaultCellEditor
   */
  public EachRowEditor(JTable table) {
    this.table = table;
    editors = new Hashtable();
    defaultEditor = new DefaultCellEditor(new JTextField());
  }
  /**
   * @param row
   *            table row
   * @param editor
   *            table cell editor
   */
  public void setEditorAt(int row, TableCellEditor editor) {
    editors.put(new Integer(row), editor);
  }
  public Component getTableCellEditorComponent(JTable table, Object value,
      boolean isSelected, int row, int column) {
    //editor = (TableCellEditor)editors.get(new Integer(row));
    //if (editor == null) {
    //  editor = defaultEditor;
    //}
    return editor.getTableCellEditorComponent(table, value, isSelected,
        row, column);
  }
  public Object getCellEditorValue() {
    return editor.getCellEditorValue();
  }
  public boolean stopCellEditing() {
    return editor.stopCellEditing();
  }
  public void cancelCellEditing() {
    editor.cancelCellEditing();
  }
  public boolean isCellEditable(EventObject anEvent) {
    selectEditor((MouseEvent) anEvent);
    return editor.isCellEditable(anEvent);
  }
  public void addCellEditorListener(CellEditorListener l) {
    editor.addCellEditorListener(l);
  }
  public void removeCellEditorListener(CellEditorListener l) {
    editor.removeCellEditorListener(l);
  }
  public boolean shouldSelectCell(EventObject anEvent) {
    selectEditor((MouseEvent) anEvent);
    return editor.shouldSelectCell(anEvent);
  }
  protected void selectEditor(MouseEvent e) {
    int row;
    if (e == null) {
      row = table.getSelectionModel().getAnchorSelectionIndex();
    } else {
      row = table.rowAtPoint(e.getPoint());
    }
    editor = (TableCellEditor) editors.get(new Integer(row));
    if (editor == null) {
      editor = defaultEditor;
    }
  }
}





Editable Header Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.ruponent;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import javax.swing.DefaultCellEditor;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
 * @version 1.0 08/22/99
 */
public class EditableHeaderTableExample extends JFrame {
  public EditableHeaderTableExample() {
    super("EditableHeader Example");
    JTable table = new JTable(7, 5);
    TableColumnModel columnModel = table.getColumnModel();
    table.setTableHeader(new EditableHeader(columnModel));
    JScrollPane pane = new JScrollPane(table);
    getContentPane().add(pane);
  }
  public static void main(String[] args) {
    EditableHeaderTableExample frame = new EditableHeaderTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(300, 100);
    frame.setVisible(true);
  }
}
class EditableHeader extends JTableHeader implements CellEditorListener {
  public final int HEADER_ROW = -10;
  transient protected int editingColumn;
  transient protected TableCellEditor cellEditor;
  transient protected Component editorComp;
  public EditableHeader(TableColumnModel columnModel) {
    super(columnModel);
    setReorderingAllowed(false);
    cellEditor = null;
    recreateTableColumn(columnModel);
  }
  public void updateUI() {
    setUI(new EditableHeaderUI());
    resizeAndRepaint();
    invalidate();
  }
  protected void recreateTableColumn(TableColumnModel columnModel) {
    int n = columnModel.getColumnCount();
    EditableHeaderTableColumn[] newCols = new EditableHeaderTableColumn[n];
    TableColumn[] oldCols = new TableColumn[n];
    for (int i = 0; i < n; i++) {
      oldCols[i] = columnModel.getColumn(i);
      newCols[i] = new EditableHeaderTableColumn();
      newCols[i].copyValues(oldCols[i]);
    }
    for (int i = 0; i < n; i++) {
      columnModel.removeColumn(oldCols[i]);
    }
    for (int i = 0; i < n; i++) {
      columnModel.addColumn(newCols[i]);
    }
  }
  public boolean editCellAt(int index) {
    return editCellAt(index);
  }
  public boolean editCellAt(int index, EventObject e) {
    if (cellEditor != null && !cellEditor.stopCellEditing()) {
      return false;
    }
    if (!isCellEditable(index)) {
      return false;
    }
    TableCellEditor editor = getCellEditor(index);
    if (editor != null && editor.isCellEditable(e)) {
      editorComp = prepareEditor(editor, index);
      editorComp.setBounds(getHeaderRect(index));
      add(editorComp);
      editorComp.validate();
      setCellEditor(editor);
      setEditingColumn(index);
      editor.addCellEditorListener(this);
      return true;
    }
    return false;
  }
  public boolean isCellEditable(int index) {
    if (getReorderingAllowed()) {
      return false;
    }
    int columnIndex = columnModel.getColumn(index).getModelIndex();
    EditableHeaderTableColumn col = (EditableHeaderTableColumn) columnModel
        .getColumn(columnIndex);
    return col.isHeaderEditable();
  }
  public TableCellEditor getCellEditor(int index) {
    int columnIndex = columnModel.getColumn(index).getModelIndex();
    EditableHeaderTableColumn col = (EditableHeaderTableColumn) columnModel
        .getColumn(columnIndex);
    return col.getHeaderEditor();
  }
  public void setCellEditor(TableCellEditor newEditor) {
    TableCellEditor oldEditor = cellEditor;
    cellEditor = newEditor;
    // firePropertyChange
    if (oldEditor != null && oldEditor instanceof TableCellEditor) {
      ((TableCellEditor) oldEditor)
          .removeCellEditorListener((CellEditorListener) this);
    }
    if (newEditor != null && newEditor instanceof TableCellEditor) {
      ((TableCellEditor) newEditor)
          .addCellEditorListener((CellEditorListener) this);
    }
  }
  public Component prepareEditor(TableCellEditor editor, int index) {
    Object value = columnModel.getColumn(index).getHeaderValue();
    boolean isSelected = true;
    int row = HEADER_ROW;
    JTable table = getTable();
    Component comp = editor.getTableCellEditorComponent(table, value,
        isSelected, row, index);
    if (comp instanceof JComponent) {
      ((JComponent) comp).setNextFocusableComponent(this);
    }
    return comp;
  }
  public TableCellEditor getCellEditor() {
    return cellEditor;
  }
  public Component getEditorComponent() {
    return editorComp;
  }
  public void setEditingColumn(int aColumn) {
    editingColumn = aColumn;
  }
  public int getEditingColumn() {
    return editingColumn;
  }
  public void removeEditor() {
    TableCellEditor editor = getCellEditor();
    if (editor != null) {
      editor.removeCellEditorListener(this);
      requestFocus();
      remove(editorComp);
      int index = getEditingColumn();
      Rectangle cellRect = getHeaderRect(index);
      setCellEditor(null);
      setEditingColumn(-1);
      editorComp = null;
      repaint(cellRect);
    }
  }
  public boolean isEditing() {
    return (cellEditor == null) ? false : true;
  }
  //
  // CellEditorListener
  //
  public void editingStopped(ChangeEvent e) {
    TableCellEditor editor = getCellEditor();
    if (editor != null) {
      Object value = editor.getCellEditorValue();
      int index = getEditingColumn();
      columnModel.getColumn(index).setHeaderValue(value);
      removeEditor();
    }
  }
  public void editingCanceled(ChangeEvent e) {
    removeEditor();
  }
  //
  // public void setReorderingAllowed(boolean b) {
  //   reorderingAllowed = false;
  // }
}
class EditableHeaderUI extends BasicTableHeaderUI {
  protected MouseInputListener createMouseInputListener() {
    return new MouseInputHandler((EditableHeader) header);
  }
  public class MouseInputHandler extends BasicTableHeaderUI.MouseInputHandler {
    private Component dispatchComponent;
    protected EditableHeader header;
    public MouseInputHandler(EditableHeader header) {
      this.header = header;
    }
    private void setDispatchComponent(MouseEvent e) {
      Component editorComponent = header.getEditorComponent();
      Point p = e.getPoint();
      Point p2 = SwingUtilities.convertPoint(header, p, editorComponent);
      dispatchComponent = SwingUtilities.getDeepestComponentAt(
          editorComponent, p2.x, p2.y);
    }
    private boolean repostEvent(MouseEvent e) {
      if (dispatchComponent == null) {
        return false;
      }
      MouseEvent e2 = SwingUtilities.convertMouseEvent(header, e,
          dispatchComponent);
      dispatchComponent.dispatchEvent(e2);
      return true;
    }
    public void mousePressed(MouseEvent e) {
      if (!SwingUtilities.isLeftMouseButton(e)) {
        return;
      }
      super.mousePressed(e);
      if (header.getResizingColumn() == null) {
        Point p = e.getPoint();
        TableColumnModel columnModel = header.getColumnModel();
        int index = columnModel.getColumnIndexAtX(p.x);
        if (index != -1) {
          if (header.editCellAt(index, e)) {
            setDispatchComponent(e);
            repostEvent(e);
          }
        }
      }
    }
    public void mouseReleased(MouseEvent e) {
      super.mouseReleased(e);
      if (!SwingUtilities.isLeftMouseButton(e)) {
        return;
      }
      repostEvent(e);
      dispatchComponent = null;
    }
  }
}
class EditableHeaderTableColumn extends TableColumn {
  protected TableCellEditor headerEditor;
  protected boolean isHeaderEditable;
  public EditableHeaderTableColumn() {
    setHeaderEditor(createDefaultHeaderEditor());
    isHeaderEditable = true;
  }
  public void setHeaderEditor(TableCellEditor headerEditor) {
    this.headerEditor = headerEditor;
  }
  public TableCellEditor getHeaderEditor() {
    return headerEditor;
  }
  public void setHeaderEditable(boolean isEditable) {
    isHeaderEditable = isEditable;
  }
  public boolean isHeaderEditable() {
    return isHeaderEditable;
  }
  public void copyValues(TableColumn base) {
    modelIndex = base.getModelIndex();
    identifier = base.getIdentifier();
    width = base.getWidth();
    minWidth = base.getMinWidth();
    setPreferredWidth(base.getPreferredWidth());
    maxWidth = base.getMaxWidth();
    headerRenderer = base.getHeaderRenderer();
    headerValue = base.getHeaderValue();
    cellRenderer = base.getCellRenderer();
    cellEditor = base.getCellEditor();
    isResizable = base.getResizable();
  }
  protected TableCellEditor createDefaultHeaderEditor() {
    return new DefaultCellEditor(new JTextField());
  }
}





Editable Header Table Example 2

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html

import java.awt.ruponent;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
 * @version 1.0 08/22/99
 */
public class EditableHeaderTableExample2 extends JFrame {
  public EditableHeaderTableExample2() {
    super("EditableHeader Example");
    JTable table = new JTable(7, 5);
    TableColumnModel columnModel = table.getColumnModel();
    table.setTableHeader(new EditableHeader(columnModel));
    String[] items = { "Dog", "Cat" };
    JComboBox combo = new JComboBox();
    for (int i = 0; i < items.length; i++) {
      combo.addItem(items[i]);
    }
    ComboRenderer renderer = new ComboRenderer(items);
    EditableHeaderTableColumn col;
    // column 1
    col = (EditableHeaderTableColumn) table.getColumnModel().getColumn(1);
    col.setHeaderValue(combo.getItemAt(0));
    col.setHeaderRenderer(renderer);
    col.setHeaderEditor(new DefaultCellEditor(combo));
    // column 3
    col = (EditableHeaderTableColumn) table.getColumnModel().getColumn(3);
    col.setHeaderValue(combo.getItemAt(0));
    //col.setHeaderRenderer(renderer);
    col.setHeaderEditor(new DefaultCellEditor(combo));
    JScrollPane pane = new JScrollPane(table);
    getContentPane().add(pane);
  }
  class ComboRenderer extends JComboBox implements TableCellRenderer {
    ComboRenderer(String[] items) {
      for (int i = 0; i < items.length; i++) {
        addItem(items[i]);
      }
    }
    public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column) {
      setSelectedItem(value);
      return this;
    }
  }
  public static void main(String[] args) {
    EditableHeaderTableExample2 frame = new EditableHeaderTableExample2();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(300, 100);
    frame.setVisible(true);
  }
}
class EditableHeader extends JTableHeader implements CellEditorListener {
  public final int HEADER_ROW = -10;
  transient protected int editingColumn;
  transient protected TableCellEditor cellEditor;
  transient protected Component editorComp;
  public EditableHeader(TableColumnModel columnModel) {
    super(columnModel);
    setReorderingAllowed(false);
    cellEditor = null;
    recreateTableColumn(columnModel);
  }
  public void updateUI() {
    setUI(new EditableHeaderUI());
    resizeAndRepaint();
    invalidate();
  }
  protected void recreateTableColumn(TableColumnModel columnModel) {
    int n = columnModel.getColumnCount();
    EditableHeaderTableColumn[] newCols = new EditableHeaderTableColumn[n];
    TableColumn[] oldCols = new TableColumn[n];
    for (int i = 0; i < n; i++) {
      oldCols[i] = columnModel.getColumn(i);
      newCols[i] = new EditableHeaderTableColumn();
      newCols[i].copyValues(oldCols[i]);
    }
    for (int i = 0; i < n; i++) {
      columnModel.removeColumn(oldCols[i]);
    }
    for (int i = 0; i < n; i++) {
      columnModel.addColumn(newCols[i]);
    }
  }
  public boolean editCellAt(int index) {
    return editCellAt(index);
  }
  public boolean editCellAt(int index, EventObject e) {
    if (cellEditor != null && !cellEditor.stopCellEditing()) {
      return false;
    }
    if (!isCellEditable(index)) {
      return false;
    }
    TableCellEditor editor = getCellEditor(index);
    if (editor != null && editor.isCellEditable(e)) {
      editorComp = prepareEditor(editor, index);
      editorComp.setBounds(getHeaderRect(index));
      add(editorComp);
      editorComp.validate();
      setCellEditor(editor);
      setEditingColumn(index);
      editor.addCellEditorListener(this);
      return true;
    }
    return false;
  }
  public boolean isCellEditable(int index) {
    if (getReorderingAllowed()) {
      return false;
    }
    int columnIndex = columnModel.getColumn(index).getModelIndex();
    EditableHeaderTableColumn col = (EditableHeaderTableColumn) columnModel
        .getColumn(columnIndex);
    return col.isHeaderEditable();
  }
  public TableCellEditor getCellEditor(int index) {
    int columnIndex = columnModel.getColumn(index).getModelIndex();
    EditableHeaderTableColumn col = (EditableHeaderTableColumn) columnModel
        .getColumn(columnIndex);
    return col.getHeaderEditor();
  }
  public void setCellEditor(TableCellEditor newEditor) {
    TableCellEditor oldEditor = cellEditor;
    cellEditor = newEditor;
    // firePropertyChange
    if (oldEditor != null && oldEditor instanceof TableCellEditor) {
      ((TableCellEditor) oldEditor)
          .removeCellEditorListener((CellEditorListener) this);
    }
    if (newEditor != null && newEditor instanceof TableCellEditor) {
      ((TableCellEditor) newEditor)
          .addCellEditorListener((CellEditorListener) this);
    }
  }
  public Component prepareEditor(TableCellEditor editor, int index) {
    Object value = columnModel.getColumn(index).getHeaderValue();
    boolean isSelected = true;
    int row = HEADER_ROW;
    JTable table = getTable();
    Component comp = editor.getTableCellEditorComponent(table, value,
        isSelected, row, index);
    if (comp instanceof JComponent) {
      ((JComponent) comp).setNextFocusableComponent(this);
    }
    return comp;
  }
  public TableCellEditor getCellEditor() {
    return cellEditor;
  }
  public Component getEditorComponent() {
    return editorComp;
  }
  public void setEditingColumn(int aColumn) {
    editingColumn = aColumn;
  }
  public int getEditingColumn() {
    return editingColumn;
  }
  public void removeEditor() {
    TableCellEditor editor = getCellEditor();
    if (editor != null) {
      editor.removeCellEditorListener(this);
      requestFocus();
      remove(editorComp);
      int index = getEditingColumn();
      Rectangle cellRect = getHeaderRect(index);
      setCellEditor(null);
      setEditingColumn(-1);
      editorComp = null;
      repaint(cellRect);
    }
  }
  public boolean isEditing() {
    return (cellEditor == null) ? false : true;
  }
  //
  // CellEditorListener
  //
  public void editingStopped(ChangeEvent e) {
    TableCellEditor editor = getCellEditor();
    if (editor != null) {
      Object value = editor.getCellEditorValue();
      int index = getEditingColumn();
      columnModel.getColumn(index).setHeaderValue(value);
      removeEditor();
    }
  }
  public void editingCanceled(ChangeEvent e) {
    removeEditor();
  }
  //
  // public void setReorderingAllowed(boolean b) {
  //   reorderingAllowed = false;
  // }
}
class EditableHeaderUI extends BasicTableHeaderUI {
  protected MouseInputListener createMouseInputListener() {
    return new MouseInputHandler((EditableHeader) header);
  }
  public class MouseInputHandler extends BasicTableHeaderUI.MouseInputHandler {
    private Component dispatchComponent;
    protected EditableHeader header;
    public MouseInputHandler(EditableHeader header) {
      this.header = header;
    }
    private void setDispatchComponent(MouseEvent e) {
      Component editorComponent = header.getEditorComponent();
      Point p = e.getPoint();
      Point p2 = SwingUtilities.convertPoint(header, p, editorComponent);
      dispatchComponent = SwingUtilities.getDeepestComponentAt(
          editorComponent, p2.x, p2.y);
    }
    private boolean repostEvent(MouseEvent e) {
      if (dispatchComponent == null) {
        return false;
      }
      MouseEvent e2 = SwingUtilities.convertMouseEvent(header, e,
          dispatchComponent);
      dispatchComponent.dispatchEvent(e2);
      return true;
    }
    public void mousePressed(MouseEvent e) {
      if (!SwingUtilities.isLeftMouseButton(e)) {
        return;
      }
      super.mousePressed(e);
      if (header.getResizingColumn() == null) {
        Point p = e.getPoint();
        TableColumnModel columnModel = header.getColumnModel();
        int index = columnModel.getColumnIndexAtX(p.x);
        if (index != -1) {
          if (header.editCellAt(index, e)) {
            setDispatchComponent(e);
            repostEvent(e);
          }
        }
      }
    }
    public void mouseReleased(MouseEvent e) {
      super.mouseReleased(e);
      if (!SwingUtilities.isLeftMouseButton(e)) {
        return;
      }
      repostEvent(e);
      dispatchComponent = null;
    }
  }
}
class EditableHeaderTableColumn extends TableColumn {
  protected TableCellEditor headerEditor;
  protected boolean isHeaderEditable;
  public EditableHeaderTableColumn() {
    setHeaderEditor(createDefaultHeaderEditor());
    isHeaderEditable = true;
  }
  public void setHeaderEditor(TableCellEditor headerEditor) {
    this.headerEditor = headerEditor;
  }
  public TableCellEditor getHeaderEditor() {
    return headerEditor;
  }
  public void setHeaderEditable(boolean isEditable) {
    isHeaderEditable = isEditable;
  }
  public boolean isHeaderEditable() {
    return isHeaderEditable;
  }
  public void copyValues(TableColumn base) {
    modelIndex = base.getModelIndex();
    identifier = base.getIdentifier();
    width = base.getWidth();
    minWidth = base.getMinWidth();
    setPreferredWidth(base.getPreferredWidth());
    maxWidth = base.getMaxWidth();
    headerRenderer = base.getHeaderRenderer();
    headerValue = base.getHeaderValue();
    cellRenderer = base.getCellRenderer();
    cellEditor = base.getCellEditor();
    isResizable = base.getResizable();
  }
  protected TableCellEditor createDefaultHeaderEditor() {
    return new DefaultCellEditor(new JTextField());
  }
}





Editable Highlight Currency Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class EditableHighlightCurrencyTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Editable Highlighted Currency Table");
    JTable tbl = new JTable(new EditableCurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tbl.setShowHorizontalLines(false);
    tbl.setIntercellSpacing(new Dimension(1, 0));
    // Add the stripe renderer in the leftmost four columns.
    StripedTableCellRenderer.installInColumn(tbl, 0, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 1, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 2, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 3, Color.lightGray,
        Color.white, null, null);
    // Add the highlight renderer to the difference column.
    // The following comparator makes it highlight
    // cells with negative numeric values.
    Comparator cmp = new Comparator() {
      public boolean shouldHighlight(JTable tbl, Object value, int row,
          int column) {
        if (value instanceof Number) {
          double columnValue = ((Number) value).doubleValue();
          return columnValue < (double) 0.0;
        }
        return false;
      }
    };
    tcm.getColumn(3).setCellRenderer(
        new HighlightRenderer(cmp, null, Color.pink, Color.black,
            Color.pink.darker(), Color.white));
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class EditableCurrencyTableModel extends CurrencyTableModel {
  public boolean isCellEditable(int row, int column) {
    return column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN;
  }
  public void setValueAt(Object value, int row, int column) {
    try {
      if (column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN) {
        Double newObjectValue; // New value as an Object
        double newValue; // double, for validity checking
        if (value instanceof Number) {
          // Convert Number to Double
          newValue = ((Number) value).doubleValue();
          newObjectValue = new Double(newValue);
        } else if (value instanceof String) {
          // Convert a String to a Double
          newObjectValue = new Double((String) value);
          newValue = newObjectValue.doubleValue();
        } else {
          // Unrecognized - ignore
          return;
        }
        if (newValue > (double) 0.0) {
          // Store new value, but reject zero or negative values
          data[row][column] = newObjectValue;
          data[row][DIFF_COLUMN] = new Double(
              ((Double) data[row][NEW_RATE_COLUMN]).doubleValue()
                  - ((Double) data[row][OLD_RATE_COLUMN])
                      .doubleValue());
          fireTableRowsUpdated(row, row);
        }
      }
    } catch (NumberFormatException e) {
      // Ignore a badly-formatted number
    }
  }
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon) value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}
interface Comparator {
  public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
      int column);
}
class HighlightRenderer implements TableCellRenderer {
  public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
      Color backColor, Color foreColor, Color highlightBack,
      Color highlightFore) {
    this.cmp = cmp;
    this.targetRenderer = targetRenderer;
    this.backColor = backColor;
    this.foreColor = foreColor;
    this.highlightBack = highlightBack;
    this.highlightFore = highlightFore;
  }
  public Component getTableCellRendererComponent(JTable tbl, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
    }
    Component comp = renderer.getTableCellRendererComponent(tbl, value,
        isSelected, hasFocus, row, column);
    if (isSelected == false && hasFocus == false && value != null) {
      if (cmp.shouldHighlight(tbl, value, row, column)) {
        comp.setForeground(highlightFore);
        comp.setBackground(highlightBack);
      } else {
        comp.setForeground(foreColor);
        comp.setBackground(backColor);
      }
    }
    return comp;
  }
  protected Comparator cmp;
  protected TableCellRenderer targetRenderer;
  protected Color backColor;
  protected Color foreColor;
  protected Color highlightBack;
  protected Color highlightFore;
}





Fixed Table Column Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */
import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.UIManager;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.AbstractTableModel;
/**
 * @version 1.0 12/05/98
 */
public class FixedColumnExample extends JFrame {
  Object[][] data;
  Object[] column;
  JTable fixedTable, table;
  public FixedColumnExample() {
    super("Fixed Column Example");
    setSize(400, 150);
    data = new Object[][] { { "1", "11", "A", "", "", "", "", "" },
        { "2", "22", "", "B", "", "", "", "" },
        { "3", "33", "", "", "C", "", "", "" },
        { "4", "44", "", "", "", "D", "", "" },
        { "5", "55", "", "", "", "", "E", "" },
        { "6", "66", "", "", "", "", "", "F" } };
    column = new Object[] { "fixed 1", "fixed 2", "a", "b", "c", "d", "e",
        "f" };
    AbstractTableModel fixedModel = new AbstractTableModel() {
      public int getColumnCount() {
        return 2;
      }
      public int getRowCount() {
        return data.length;
      }
      public String getColumnName(int col) {
        return (String) column[col];
      }
      public Object getValueAt(int row, int col) {
        return data[row][col];
      }
    };
    AbstractTableModel model = new AbstractTableModel() {
      public int getColumnCount() {
        return column.length - 2;
      }
      public int getRowCount() {
        return data.length;
      }
      public String getColumnName(int col) {
        return (String) column[col + 2];
      }
      public Object getValueAt(int row, int col) {
        return data[row][col + 2];
      }
      public void setValueAt(Object obj, int row, int col) {
        data[row][col + 2] = obj;
      }
      public boolean CellEditable(int row, int col) {
        return true;
      }
    };
    fixedTable = new JTable(fixedModel) {
      public void valueChanged(ListSelectionEvent e) {
        super.valueChanged(e);
        checkSelection(true);
      }
    };
    table = new JTable(model) {
      public void valueChanged(ListSelectionEvent e) {
        super.valueChanged(e);
        checkSelection(false);
      }
    };
    fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    fixedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    JScrollPane scroll = new JScrollPane(table);
    JViewport viewport = new JViewport();
    viewport.setView(fixedTable);
    viewport.setPreferredSize(fixedTable.getPreferredSize());
    scroll.setRowHeaderView(viewport);
    scroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedTable
        .getTableHeader());
    getContentPane().add(scroll, BorderLayout.CENTER);
  }
  private void checkSelection(boolean isFixedTable) {
    int fixedSelectedIndex = fixedTable.getSelectedRow();
    int selectedIndex = table.getSelectedRow();
    if (fixedSelectedIndex != selectedIndex) {
      if (isFixedTable) {
        table.setRowSelectionInterval(fixedSelectedIndex,
            fixedSelectedIndex);
      } else {
        fixedTable
            .setRowSelectionInterval(selectedIndex, selectedIndex);
      }
    }
  }
  public static void main(String[] args) {
    FixedColumnExample frame = new FixedColumnExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setVisible(true);
  }
}





Fixed Table Row Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1beta1) */
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
/**
 * @version 1.0 03/05/99
 */
public class FixedRowExample extends JFrame {
  Object[][] data;
  Object[] column;
  JTable fixedTable, table;
  private int FIXED_NUM = 2;
  public FixedRowExample() {
    super("Fixed Row Example");
    data = new Object[][] { { "a", "", "", "", "", "" },
        { "", "b", "", "", "", "" }, { "", "", "c", "", "", "" },
        { "", "", "", "d", "", "" }, { "", "", "", "", "e", "" },
        { "", "", "", "", "", "f" },
        { "fixed1", "", "", "", "", "", "", "" },
        { "fixed2", "", "", "", "", "", "", "" } };
    column = new Object[] { "A", "B", "C", "D", "E", "F" };
    AbstractTableModel model = new AbstractTableModel() {
      public int getColumnCount() {
        return column.length;
      }
      public int getRowCount() {
        return data.length - FIXED_NUM;
      }
      public String getColumnName(int col) {
        return (String) column[col];
      }
      public Object getValueAt(int row, int col) {
        return data[row][col];
      }
      public void setValueAt(Object obj, int row, int col) {
        data[row][col] = obj;
      }
      public boolean CellEditable(int row, int col) {
        return true;
      }
    };
    AbstractTableModel fixedModel = new AbstractTableModel() {
      public int getColumnCount() {
        return column.length;
      }
      public int getRowCount() {
        return FIXED_NUM;
      }
      public Object getValueAt(int row, int col) {
        return data[row + (data.length - FIXED_NUM)][col];
      }
    };
    table = new JTable(model);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    fixedTable = new JTable(fixedModel);
    fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    fixedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    JScrollPane scroll = new JScrollPane(table);
    scroll
        .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    JScrollPane fixedScroll = new JScrollPane(fixedTable) {
      public void setColumnHeaderView(Component view) {
      } // work around
    }; //
    // fixedScroll.setColumnHeader(null);
    fixedScroll
        .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    JScrollBar bar = fixedScroll.getVerticalScrollBar();
    JScrollBar dummyBar = new JScrollBar() {
      public void paint(Graphics g) {
      }
    };
    dummyBar.setPreferredSize(bar.getPreferredSize());
    fixedScroll.setVerticalScrollBar(dummyBar);
    final JScrollBar bar1 = scroll.getHorizontalScrollBar();
    JScrollBar bar2 = fixedScroll.getHorizontalScrollBar();
    bar2.addAdjustmentListener(new AdjustmentListener() {
      public void adjustmentValueChanged(AdjustmentEvent e) {
        bar1.setValue(e.getValue());
      }
    });
    scroll.setPreferredSize(new Dimension(400, 100));
    fixedScroll.setPreferredSize(new Dimension(400, 52)); // Hmm...
    getContentPane().add(scroll, BorderLayout.CENTER);
    getContentPane().add(fixedScroll, BorderLayout.SOUTH);
  }
  public static void main(String[] args) {
    FixedRowExample frame = new FixedRowExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.pack();
    frame.setVisible(true);
  }
}





Fraction Currency Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumnModel;
public class FractionCurrencyTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Fraction Currency Table");
    JTable tbl = new JTable(new CurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}





Groupable(Group) Header Example

 
/* (swing1.1beta3)
 *example from 
 http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html 
 *
 */
/* (swing1.1beta3)
 *
 * |-----------------------------------------------------|
 * |        |       Name      |         Language         |
 * |        |-----------------|--------------------------|
 * |  SNo.  |        |        |        |      Others     |
 * |        |   1    |    2   | Native |-----------------|
 * |        |        |        |        |   2    |   3    |  
 * |-----------------------------------------------------|
 * |        |        |        |        |        |        |
 *
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

/**
 * @version 1.0 11/09/98
 */
public class GroupableHeaderExample extends JFrame {
  GroupableHeaderExample() {
    super( "Groupable Header Example" );
    DefaultTableModel dm = new DefaultTableModel();
    dm.setDataVector(new Object[][]{
      {"119","foo","bar","ja","ko","zh"},
      {"911","bar","foo","en","fr","pt"}},
    new Object[]{"SNo.","1","2","Native","2","3"});
    JTable table = new JTable( dm ) {
      protected JTableHeader createDefaultTableHeader() {
          return new GroupableTableHeader(columnModel);
      }
    };
    
    
    TableColumnModel cm = table.getColumnModel();
    ColumnGroup g_name = new ColumnGroup("Name");
    g_name.add(cm.getColumn(1));
    g_name.add(cm.getColumn(2));
    ColumnGroup g_lang = new ColumnGroup("Language");
    g_lang.add(cm.getColumn(3));
    ColumnGroup g_other = new ColumnGroup("Others");
    g_other.add(cm.getColumn(4));
    g_other.add(cm.getColumn(5));
    g_lang.add(g_other);
    
    GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();
    header.addColumnGroup(g_name);
    header.addColumnGroup(g_lang);
    JScrollPane scroll = new JScrollPane( table );
    getContentPane().add( scroll );
    setSize( 400, 120 );   
  }
  public static void main(String[] args) {
    GroupableHeaderExample frame = new GroupableHeaderExample();
    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing( WindowEvent e ) {
  System.exit(0);
      }
    });
    frame.setVisible(true);
  }
}
/*
 * (swing1.1beta3)
 * 
 */
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
 
/**
  * GroupableTableHeader
  *
  * @version 1.0 10/20/98
  * @author Nobuo Tamemasa
  */
public class GroupableTableHeader extends JTableHeader {
  private static final String uiClassID = "GroupableTableHeaderUI";
  protected Vector columnGroups = null;
    
  public GroupableTableHeader(TableColumnModel model) {
    super(model);
    setUI(new GroupableTableHeaderUI());
    setReorderingAllowed(false);
  }
  public void updateUI(){
   setUI(new GroupableTableHeaderUI());
  }
  
  public void setReorderingAllowed(boolean b) {
    reorderingAllowed = false;
  }
    
  public void addColumnGroup(ColumnGroup g) {
    if (columnGroups == null) {
      columnGroups = new Vector();
    }
    columnGroups.addElement(g);
  }
  public Enumeration getColumnGroups(TableColumn col) {
    if (columnGroups == null) return null;
    Enumeration e = columnGroups.elements();
    while (e.hasMoreElements()) {
      ColumnGroup cGroup = (ColumnGroup)e.nextElement();
      Vector v_ret = (Vector)cGroup.getColumnGroups(col,new Vector());
      if (v_ret != null) { 
  return v_ret.elements();
      }
    }
    return null;
  }
  
  public void setColumnMargin() {
    if (columnGroups == null) return;
    int columnMargin = getColumnModel().getColumnMargin();
    Enumeration e = columnGroups.elements();
    while (e.hasMoreElements()) {
      ColumnGroup cGroup = (ColumnGroup)e.nextElement();
      cGroup.setColumnMargin(columnMargin);
    }
  }
  
}
/*
 * (swing1.1beta3)
 * 
 */
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.*;

public class GroupableTableHeaderUI extends BasicTableHeaderUI {
  
  public void paint(Graphics g, JComponent c) {
    Rectangle clipBounds = g.getClipBounds();
    if (header.getColumnModel() == null) return;
    ((GroupableTableHeader)header).setColumnMargin();
    int column = 0;
    Dimension size = header.getSize();
    Rectangle cellRect  = new Rectangle(0, 0, size.width, size.height);
    Hashtable h = new Hashtable();
    int columnMargin = header.getColumnModel().getColumnMargin();
    
    Enumeration enumeration = header.getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
      cellRect.height = size.height;
      cellRect.y      = 0;
      TableColumn aColumn = (TableColumn)enumeration.nextElement();
      Enumeration cGroups = ((GroupableTableHeader)header).getColumnGroups(aColumn);
      if (cGroups != null) {
        int groupHeight = 0;
        while (cGroups.hasMoreElements()) {
          ColumnGroup cGroup = (ColumnGroup)cGroups.nextElement();
          Rectangle groupRect = (Rectangle)h.get(cGroup);
          if (groupRect == null) {
            groupRect = new Rectangle(cellRect);
            Dimension d = cGroup.getSize(header.getTable());
            groupRect.width  = d.width;
            groupRect.height = d.height;    
            h.put(cGroup, groupRect);
          }
          paintCell(g, groupRect, cGroup);
          groupHeight += groupRect.height;
          cellRect.height = size.height - groupHeight;
          cellRect.y      = groupHeight;
        }
      }      
      cellRect.width = aColumn.getWidth() + columnMargin;
      if (cellRect.intersects(clipBounds)) {
        paintCell(g, cellRect, column);
      }
      cellRect.x += cellRect.width;
      column++;
    }
  }
  private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) {
    TableColumn aColumn = header.getColumnModel().getColumn(columnIndex);
    TableCellRenderer renderer = aColumn.getHeaderRenderer();
    //revised by jexp.ru
    renderer = new DefaultTableCellRenderer(){
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
          JLabel header = new JLabel();
            header.setForeground(table.getTableHeader().getForeground());
            header.setBackground(table.getTableHeader().getBackground());
            header.setFont(table.getTableHeader().getFont());
          header.setHorizontalAlignment(JLabel.CENTER);
          header.setText(value.toString());
          header.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
            return header;
        }
    
    };
    Component c = renderer.getTableCellRendererComponent(
        header.getTable(), aColumn.getHeaderValue(),false, false, -1, columnIndex);
        
        c.setBackground(UIManager.getColor("control"));
      
    rendererPane.add(c);
    rendererPane.paintComponent(g, c, header, cellRect.x, cellRect.y,
        cellRect.width, cellRect.height, true);
  }
  private void paintCell(Graphics g, Rectangle cellRect,ColumnGroup cGroup) {
    TableCellRenderer renderer = cGroup.getHeaderRenderer();
      //revised by jexp.ru
     // if(renderer == null){
//      return ;
  //    }
    Component component = renderer.getTableCellRendererComponent(
      header.getTable(), cGroup.getHeaderValue(),false, false, -1, -1);
    rendererPane.add(component);
    rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
        cellRect.width, cellRect.height, true);
  }
  private int getHeaderHeight() {
    int height = 0;
    TableColumnModel columnModel = header.getColumnModel();
    for(int column = 0; column < columnModel.getColumnCount(); column++) {
      TableColumn aColumn = columnModel.getColumn(column);
      TableCellRenderer renderer = aColumn.getHeaderRenderer();
      //revised by jexp.ru
      if(renderer == null){
      return 60;
      }
      
      Component comp = renderer.getTableCellRendererComponent(
        header.getTable(), aColumn.getHeaderValue(), false, false,-1, column);
      int cHeight = comp.getPreferredSize().height;
      Enumeration e = ((GroupableTableHeader)header).getColumnGroups(aColumn);      
      if (e != null) {
        while (e.hasMoreElements()) {
          ColumnGroup cGroup = (ColumnGroup)e.nextElement();
          cHeight += cGroup.getSize(header.getTable()).height;
        }
      }
      height = Math.max(height, cHeight);
    }
    return height;
  }
  private Dimension createHeaderSize(long width) {
    TableColumnModel columnModel = header.getColumnModel();
    width += columnModel.getColumnMargin() * columnModel.getColumnCount();
    if (width > Integer.MAX_VALUE) {
      width = Integer.MAX_VALUE;
    }
    return new Dimension((int)width, getHeaderHeight());
  }
  public Dimension getPreferredSize(JComponent c) {
    long width = 0;
    Enumeration enumeration = header.getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
      TableColumn aColumn = (TableColumn)enumeration.nextElement();
      width = width + aColumn.getPreferredWidth();
    }
    return createHeaderSize(width);
  }
}
/*
 * (swing1.1beta3)
 * 
 */
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

/**
  * ColumnGroup
  *
  * @version 1.0 10/20/98
  * @author Nobuo Tamemasa
  */
 
class ColumnGroup {
  protected TableCellRenderer renderer;
  protected Vector v;
  protected String text;
  protected int margin=0;
  public ColumnGroup(String text) {
    this(null,text);
  }
  public ColumnGroup(TableCellRenderer renderer,String text) {
    if (renderer == null) {
      this.renderer = new DefaultTableCellRenderer() {
  public Component getTableCellRendererComponent(JTable table, Object value,
                         boolean isSelected, boolean hasFocus, int row, int column) {
    JTableHeader header = table.getTableHeader();
    if (header != null) {
      setForeground(header.getForeground());
      setBackground(header.getBackground());
      setFont(header.getFont());
    }
          setHorizontalAlignment(JLabel.CENTER);
          setText((value == null) ? "" : value.toString());
    setBorder(UIManager.getBorder("TableHeader.cellBorder"));
    return this;
        }
      };
    } else {
      this.renderer = renderer;
    }
    this.text = text;
    v = new Vector();
  }
  
  /**
   * @param obj    TableColumn or ColumnGroup
   */
  public void add(Object obj) {
    if (obj == null) { return; }
    v.addElement(obj);
  }
  
  /**
   * @param c    TableColumn
   * @param v    ColumnGroups
   */
  public Vector getColumnGroups(TableColumn c, Vector g) {
    g.addElement(this);
    if (v.contains(c)) return g;    
    Enumeration e = v.elements();
    while (e.hasMoreElements()) {
      Object obj = e.nextElement();
      if (obj instanceof ColumnGroup) {
        Vector groups = 
          (Vector)((ColumnGroup)obj).getColumnGroups(c,(Vector)g.clone());
        if (groups != null) return groups;
      }
    }
    return null;
  }
    
  public TableCellRenderer getHeaderRenderer() {
    return renderer;
  }
    
  public void setHeaderRenderer(TableCellRenderer renderer) {
    if (renderer != null) {
      this.renderer = renderer;
    }
  }
    
  public Object getHeaderValue() {
    return text;
  }
  
  public Dimension getSize(JTable table) {
    Component comp = renderer.getTableCellRendererComponent(
        table, getHeaderValue(), false, false,-1, -1);
    int height = comp.getPreferredSize().height; 
    int width  = 0;
    Enumeration e = v.elements();
    while (e.hasMoreElements()) {
      Object obj = e.nextElement();
      if (obj instanceof TableColumn) {
        TableColumn aColumn = (TableColumn)obj;
        width += aColumn.getWidth();
        width += margin;
      } else {
        width += ((ColumnGroup)obj).getSize(table).width;
      }
    }
    return new Dimension(width, height);
  }
  public void setColumnMargin(int margin) {
    this.margin = margin;
    Enumeration e = v.elements();
    while (e.hasMoreElements()) {
      Object obj = e.nextElement();
      if (obj instanceof ColumnGroup) {
        ((ColumnGroup)obj).setColumnMargin(margin);
      }
    }
  }
}





Hide Column Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1beta2) */
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Stack;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ScrollPaneLayout;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
 * @version 1.0 05/31/99
 */
public class HideColumnTableExample extends JFrame {
  public HideColumnTableExample() {
    super("HideColumnTable Example");
    JTable table = new JTable(5, 7);
    ColumnButtonScrollPane pane = new ColumnButtonScrollPane(table);
    getContentPane().add(pane);
  }
  public static void main(String[] args) {
    HideColumnTableExample frame = new HideColumnTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(400, 100);
    frame.setVisible(true);
  }
}
class ColumnButtonScrollPane extends JScrollPane {
  Component columnButton;
  public ColumnButtonScrollPane(JTable table) {
    super(table);
    TableColumnModel cm = table.getColumnModel();
    LimitedTableHeader header = new LimitedTableHeader(cm);
    table.setTableHeader(header);
    columnButton = createUpperCorner(header);
    setCorner(UPPER_RIGHT_CORNER, columnButton);
    setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
    ColumnButtonScrollPaneLayout layout = new ColumnButtonScrollPaneLayout();
    setLayout(layout);
    layout.syncWithScrollPane(this);
  }
  protected Component createUpperCorner(JTableHeader header) {
    ColumnButton corner = new ColumnButton(header);
    return corner;
  }
  public class LimitedTableHeader extends JTableHeader {
    public LimitedTableHeader(TableColumnModel cm) {
      super(cm);
    }
    // actually, this is a not complete way. but easy one.
    // you can see last column painted wider, short time :)
    // If you don"t like this kind cheap fake,
    // you have to overwrite the paint method in UI class.
    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      columnButton.repaint();
    }
  }
  public class ColumnButton extends JPanel {
    JTable table;
    TableColumnModel cm;
    JButton revealButton;
    JButton hideButton;
    Stack stack;
    public ColumnButton(JTableHeader header) {
      setLayout(new GridLayout(1, 2));
      setBorder(new LinesBorder(SystemColor.controlShadow, new Insets(0,
          1, 0, 0)));
      stack = new Stack();
      table = header.getTable();
      cm = table.getColumnModel();
      revealButton = createButton(header, SwingConstants.WEST);
      hideButton = createButton(header, SwingConstants.EAST);
      add(revealButton);
      add(hideButton);
      revealButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          TableColumn column = (TableColumn) stack.pop();
          cm.addColumn(column);
          if (stack.empty()) {
            revealButton.setEnabled(false);
          }
          hideButton.setEnabled(true);
          table.sizeColumnsToFit(-1);
        }
      });
      hideButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          int n = cm.getColumnCount();
          TableColumn column = cm.getColumn(n - 1);
          stack.push(column);
          cm.removeColumn(column);
          if (n < 3) {
            hideButton.setEnabled(false);
          }
          revealButton.setEnabled(true);
          table.sizeColumnsToFit(-1);
        }
      });
      if (1 < cm.getColumnCount()) {
        hideButton.setEnabled(true);
      } else {
        hideButton.setEnabled(false);
      }
      revealButton.setEnabled(false);
    }
    protected JButton createButton(JTableHeader header, int direction) {
      //int iconHeight = header.getPreferredSize().height - 6;
      int iconHeight = 8;
      JButton button = new JButton();
      button.setIcon(new ArrowIcon(iconHeight, direction, true));
      button.setDisabledIcon(new ArrowIcon(iconHeight, direction, false));
      button.setRequestFocusEnabled(false);
      button.setForeground(header.getForeground());
      button.setBackground(header.getBackground());
      button.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
      return button;
    }
  }
}
class ColumnButtonScrollPaneLayout extends ScrollPaneLayout {
  public ColumnButtonScrollPaneLayout() {
    super.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
  }
  public void setVerticalScrollBarPolicy(int x) {
    // VERTICAL_SCROLLBAR_ALWAYS
    super.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
  }
  public void layoutContainer(Container parent) {
    super.layoutContainer(parent);
    if ((colHead == null) || (!colHead.isVisible()) || (upperRight == null)
        || (vsb == null)) {
      return;
    }
    Rectangle vsbR = new Rectangle(0, 0, 0, 0);
    vsbR = vsb.getBounds(vsbR);
    Rectangle colHeadR = new Rectangle(0, 0, 0, 0);
    colHeadR = colHead.getBounds(colHeadR);
    colHeadR.width -= vsbR.width;
    colHead.getBounds(colHeadR);
    Rectangle upperRightR = upperRight.getBounds();
    upperRightR.x -= vsbR.width;
    upperRightR.width += vsbR.width + 1;
    upperRight.setBounds(upperRightR);
  }
}
class LinesBorder extends AbstractBorder implements SwingConstants {
  protected int northThickness;
  protected int southThickness;
  protected int eastThickness;
  protected int westThickness;
  protected Color northColor;
  protected Color southColor;
  protected Color eastColor;
  protected Color westColor;
  public LinesBorder(Color color) {
    this(color, 1);
  }
  public LinesBorder(Color color, int thickness) {
    setColor(color);
    setThickness(thickness);
  }
  public LinesBorder(Color color, Insets insets) {
    setColor(color);
    setThickness(insets);
  }
  public void paintBorder(Component c, Graphics g, int x, int y, int width,
      int height) {
    Color oldColor = g.getColor();
    g.setColor(northColor);
    for (int i = 0; i < northThickness; i++) {
      g.drawLine(x, y + i, x + width - 1, y + i);
    }
    g.setColor(southColor);
    for (int i = 0; i < southThickness; i++) {
      g
          .drawLine(x, y + height - i - 1, x + width - 1, y + height
              - i - 1);
    }
    g.setColor(eastColor);
    for (int i = 0; i < westThickness; i++) {
      g.drawLine(x + i, y, x + i, y + height - 1);
    }
    g.setColor(westColor);
    for (int i = 0; i < eastThickness; i++) {
      g.drawLine(x + width - i - 1, y, x + width - i - 1, y + height - 1);
    }
    g.setColor(oldColor);
  }
  public Insets getBorderInsets(Component c) {
    return new Insets(northThickness, westThickness, southThickness,
        eastThickness);
  }
  public Insets getBorderInsets(Component c, Insets insets) {
    return new Insets(northThickness, westThickness, southThickness,
        eastThickness);
  }
  public boolean isBorderOpaque() {
    return true;
  }
  public void setColor(Color c) {
    northColor = c;
    southColor = c;
    eastColor = c;
    westColor = c;
  }
  public void setColor(Color c, int direction) {
    switch (direction) {
    case NORTH:
      northColor = c;
      break;
    case SOUTH:
      southColor = c;
      break;
    case EAST:
      eastColor = c;
      break;
    case WEST:
      westColor = c;
      break;
    default:
    }
  }
  public void setThickness(int n) {
    northThickness = n;
    southThickness = n;
    eastThickness = n;
    westThickness = n;
  }
  public void setThickness(Insets insets) {
    northThickness = insets.top;
    southThickness = insets.bottom;
    eastThickness = insets.right;
    westThickness = insets.left;
  }
  public void setThickness(int n, int direction) {
    switch (direction) {
    case NORTH:
      northThickness = n;
      break;
    case SOUTH:
      southThickness = n;
      break;
    case EAST:
      eastThickness = n;
      break;
    case WEST:
      westThickness = n;
      break;
    default:
    }
  }
  public void append(LinesBorder b, boolean isReplace) {
    if (isReplace) {
      northThickness = b.northThickness;
      southThickness = b.southThickness;
      eastThickness = b.eastThickness;
      westThickness = b.westThickness;
    } else {
      northThickness = Math.max(northThickness, b.northThickness);
      southThickness = Math.max(southThickness, b.southThickness);
      eastThickness = Math.max(eastThickness, b.eastThickness);
      westThickness = Math.max(westThickness, b.westThickness);
    }
  }
  public void append(Insets insets, boolean isReplace) {
    if (isReplace) {
      northThickness = insets.top;
      southThickness = insets.bottom;
      eastThickness = insets.right;
      westThickness = insets.left;
    } else {
      northThickness = Math.max(northThickness, insets.top);
      southThickness = Math.max(southThickness, insets.bottom);
      eastThickness = Math.max(eastThickness, insets.right);
      westThickness = Math.max(westThickness, insets.left);
    }
  }
}
class ArrowIcon implements Icon, SwingConstants {
  private static final int DEFAULT_SIZE = 11;
  //private static final int DEFAULT_SIZE = 5;
  private int size;
  private int iconSize;
  private int direction;
  private boolean isEnabled;
  private BasicArrowButton iconRenderer;
  public ArrowIcon(int direction, boolean isPressedView) {
    this(DEFAULT_SIZE, direction, isPressedView);
  }
  public ArrowIcon(int iconSize, int direction, boolean isEnabled) {
    this.size = iconSize / 2;
    this.iconSize = iconSize;
    this.direction = direction;
    this.isEnabled = isEnabled;
    iconRenderer = new BasicArrowButton(direction);
  }
  public void paintIcon(Component c, Graphics g, int x, int y) {
    iconRenderer.paintTriangle(g, x, y, size, direction, isEnabled);
  }
  public int getIconWidth() {
    //int retCode;
    switch (direction) {
    case NORTH:
    case SOUTH:
      return iconSize;
    case EAST:
    case WEST:
      return size;
    }
    return iconSize;
  }
  public int getIconHeight() {
    switch (direction) {
    case NORTH:
    case SOUTH:
      return size;
    case EAST:
    case WEST:
      return iconSize;
    }
    return size;
  }
}





Highlight Currency Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class HighlightCurrencyTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Highlighted Currency Table");
    JTable tbl = new JTable(new CurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tbl.setShowHorizontalLines(false);
    tbl.setIntercellSpacing(new Dimension(1, 0));
    // Add the stipe renderer.
    StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
        Color.white, null, null);
    // Add the highlight renderer to the last column.
    // The following comparator makes it highlight
    // cells with negative numeric values.
    Comparator cmp = new Comparator() {
      public boolean shouldHighlight(JTable tbl, Object value, int row,
          int column) {
        if (value instanceof Number) {
          double columnValue = ((Number) value).doubleValue();
          return columnValue < (double) 0.0;
        }
        return false;
      }
    };
    tcm.getColumn(3).setCellRenderer(
        new HighlightRenderer(cmp, null, Color.pink, Color.black,
            Color.pink.darker(), Color.white));
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon) value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}
class HighlightRenderer implements TableCellRenderer {
  public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
      Color backColor, Color foreColor, Color highlightBack,
      Color highlightFore) {
    this.cmp = cmp;
    this.targetRenderer = targetRenderer;
    this.backColor = backColor;
    this.foreColor = foreColor;
    this.highlightBack = highlightBack;
    this.highlightFore = highlightFore;
  }
  public Component getTableCellRendererComponent(JTable tbl, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
    }
    Component comp = renderer.getTableCellRendererComponent(tbl, value,
        isSelected, hasFocus, row, column);
    if (isSelected == false && hasFocus == false && value != null) {
      if (cmp.shouldHighlight(tbl, value, row, column)) {
        comp.setForeground(highlightFore);
        comp.setBackground(highlightBack);
      } else {
        comp.setForeground(foreColor);
        comp.setBackground(backColor);
      }
    }
    return comp;
  }
  protected Comparator cmp;
  protected TableCellRenderer targetRenderer;
  protected Color backColor;
  protected Color foreColor;
  protected Color highlightBack;
  protected Color highlightFore;
}
interface Comparator {
  public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
      int column);
}





Highlight Currency Table 2

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class HighlightCurrencyTable2 {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Highlighted Currency Table 2");
    JTable tbl = new JTable(new CurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tbl.setShowHorizontalLines(false);
    tbl.setIntercellSpacing(new Dimension(1, 0));
    // Add the stripe renderer.
    StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
        Color.white, null, null);
    // Add the highlight renderer to the last column.
    Comparator cmp = new Comparator() {
      public boolean shouldHighlight(JTable tbl, Object value, int row,
          int column) {
        if (value instanceof Number) {
          Object oldValueObj = tbl.getModel().getValueAt(row, 1);
          if (oldValueObj instanceof Number) {
            double oldValue = ((Number) oldValueObj).doubleValue();
            double columnValue = ((Number) value).doubleValue();
            return Math.abs(columnValue) > Math.abs(oldValue
                / (double) 10.0);
          }
        }
        return false;
      }
    };
    tcm.getColumn(3).setCellRenderer(
        new HighlightRenderer(cmp, null, Color.pink, Color.black,
            Color.pink.darker(), Color.white));
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
interface Comparator {
  public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
      int column);
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon) value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}
class HighlightRenderer implements TableCellRenderer {
  public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
      Color backColor, Color foreColor, Color highlightBack,
      Color highlightFore) {
    this.cmp = cmp;
    this.targetRenderer = targetRenderer;
    this.backColor = backColor;
    this.foreColor = foreColor;
    this.highlightBack = highlightBack;
    this.highlightFore = highlightFore;
  }
  public Component getTableCellRendererComponent(JTable tbl, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
    }
    Component comp = renderer.getTableCellRendererComponent(tbl, value,
        isSelected, hasFocus, row, column);
    if (isSelected == false && hasFocus == false && value != null) {
      if (cmp.shouldHighlight(tbl, value, row, column)) {
        comp.setForeground(highlightFore);
        comp.setBackground(highlightBack);
      } else {
        comp.setForeground(foreColor);
        comp.setBackground(backColor);
      }
    }
    return comp;
  }
  protected Comparator cmp;
  protected TableCellRenderer targetRenderer;
  protected Color backColor;
  protected Color foreColor;
  protected Color highlightBack;
  protected Color highlightFore;
}





Icon Currency Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumnModel;
public class IconCurrencyTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Icon Currency Table");
    JTable tbl = new JTable(new CurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))),
          new Double(0.6213051), new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon)value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}





Indicator Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html

/* (swing1.1) */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
/**
 * @version 1.0 03/03/99
 */
public class IndicatorTableExample extends JPanel {
  private static final int MAX = 100;
  private static final int MIN = 0;
  public IndicatorTableExample() {
    setLayout(new BorderLayout());
    DefaultTableModel dm = new DefaultTableModel() {
      public Class getColumnClass(int col) {
        switch (col) {
        case 0:
          return String.class;
        case 1:
          return Integer.class;
        case 2:
          return Integer.class;
        default:
          return Object.class;
        }
      }
      public boolean isCellEditable(int row, int col) {
        switch (col) {
        case 2:
          return false;
        default:
          return true;
        }
      }
      public void setValueAt(Object obj, int row, int col) {
        if (col != 1) {
          super.setValueAt(obj, row, col);
          return;
        }
        try {
          Integer integer = new Integer(obj.toString());
          super.setValueAt(checkMinMax(integer), row, col);
        } catch (NumberFormatException ex) {
          ex.printStackTrace();
        }
      }
    };
    dm.setDataVector(new Object[][] {
        { "not human", new Integer(100), new Integer(100) },
        { "hard worker", new Integer(76), new Integer(76) },
        { "ordinary guy", new Integer(51), new Integer(51) },
        { "lazy fellow", new Integer(12), new Integer(12) } },
        new Object[] { "Name", "Result", "Indicator" });
    JTable table = new JTable(dm);
    IndicatorCellRenderer renderer = new IndicatorCellRenderer(MIN, MAX);
    renderer.setStringPainted(true);
    renderer.setBackground(table.getBackground());
    // set limit value and fill color
    Hashtable limitColors = new Hashtable();
    limitColors.put(new Integer(0), Color.green);
    limitColors.put(new Integer(60), Color.yellow);
    limitColors.put(new Integer(80), Color.red);
    renderer.setLimits(limitColors);
    table.getColumnModel().getColumn(2).setCellRenderer(renderer);
    table.getModel().addTableModelListener(new TableModelListener() {
      public void tableChanged(TableModelEvent e) {
        if (e.getType() == TableModelEvent.UPDATE) {
          int col = e.getColumn();
          if (col == 1) {
            int row = e.getFirstRow();
            TableModel model = (TableModel) e.getSource();
            Integer value = (Integer) model.getValueAt(row, col);
            model.setValueAt(checkMinMax(value), row, ++col);
          }
        }
      }
    });
    JScrollPane pane = new JScrollPane(table);
    add(pane, BorderLayout.CENTER);
  }
  public static void main(String[] args) {
    JFrame f = new JFrame("IndicatorTable Example");
    f.getContentPane()
        .add(new IndicatorTableExample(), BorderLayout.CENTER);
    f.setSize(400, 120);
    f.setVisible(true);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
  private Integer checkMinMax(Integer value) {
    int intValue = value.intValue();
    if (intValue < MIN) {
      intValue = MIN;
    } else if (MAX < intValue) {
      intValue = MAX;
    }
    return new Integer(intValue);
  }
}
/**
 * @version 1.0 03/03/99
 */
class IndicatorCellRenderer extends JProgressBar implements TableCellRenderer {
  private Hashtable limitColors;
  private int[] limitValues;
  public IndicatorCellRenderer() {
    super(JProgressBar.HORIZONTAL);
    setBorderPainted(false);
  }
  public IndicatorCellRenderer(int min, int max) {
    super(JProgressBar.HORIZONTAL, min, max);
    setBorderPainted(false);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    int n = 0;
    if (!(value instanceof Number)) {
      String str;
      if (value instanceof String) {
        str = (String) value;
      } else {
        str = value.toString();
      }
      try {
        n = Integer.valueOf(str).intValue();
      } catch (NumberFormatException ex) {
      }
    } else {
      n = ((Number) value).intValue();
    }
    Color color = getColor(n);
    if (color != null) {
      setForeground(color);
    }
    setValue(n);
    return this;
  }
  public void setLimits(Hashtable limitColors) {
    this.limitColors = limitColors;
    int i = 0;
    int n = limitColors.size();
    limitValues = new int[n];
    Enumeration e = limitColors.keys();
    while (e.hasMoreElements()) {
      limitValues[i++] = ((Integer) e.nextElement()).intValue();
    }
    sort(limitValues);
  }
  private Color getColor(int value) {
    Color color = null;
    if (limitValues != null) {
      int i;
      for (i = 0; i < limitValues.length; i++) {
        if (limitValues[i] < value) {
          color = (Color) limitColors
              .get(new Integer(limitValues[i]));
        }
      }
    }
    return color;
  }
  private void sort(int[] a) {
    int n = a.length;
    for (int i = 0; i < n - 1; i++) {
      int k = i;
      for (int j = i + 1; j < n; j++) {
        if (a[j] < a[k]) {
          k = j;
        }
      }
      int tmp = a[i];
      a[i] = a[k];
      a[k] = tmp;
    }
  }
}





JSortTable

   
package org.tn5250j.gui;
/*

  JSortTable.java
  Created by Claude Duguay
  Copyright (c) 2002
   This was taken from a Java Pro magazine article
   http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
   I have NOT asked for permission to use this.

*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Collections;
import java.util.ruparator;
import java.util.Vector;
import javax.swing.Icon;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
public class JSortTable extends JTable implements MouseListener {
   protected int sortedColumnIndex = -1;
   protected boolean sortedColumnAscending = true;
   public JSortTable() {
      this(new DefaultSortTableModel());
   }
   public JSortTable(int rows, int cols) {
      this(new DefaultSortTableModel(rows, cols));
   }
   public JSortTable(Object[][] data, Object[] names) {
      this(new DefaultSortTableModel(data, names));
   }
   public JSortTable(Vector data, Vector names) {
      this(new DefaultSortTableModel(data, names));
   }
   public JSortTable(SortTableModel model) {
      super(model);
      initSortHeader();
   }
   public JSortTable(SortTableModel model, TableColumnModel colModel) {
      super(model, colModel);
      initSortHeader();
   }
   public JSortTable(SortTableModel model, TableColumnModel colModel,
                           ListSelectionModel selModel) {
      super(model, colModel, selModel);
      initSortHeader();
   }
   protected void initSortHeader() {
      JTableHeader header = getTableHeader();
      header.setDefaultRenderer(new SortHeaderRenderer());
      header.addMouseListener(this);
   }
   public int getSortedColumnIndex() {
      return sortedColumnIndex;
   }
   public boolean isSortedColumnAscending() {
      return sortedColumnAscending;
   }
   public void mouseReleased(MouseEvent event) {
      TableColumnModel colModel = getColumnModel();
      int index = colModel.getColumnIndexAtX(event.getX());
      int modelIndex = colModel.getColumn(index).getModelIndex();
      SortTableModel model = (SortTableModel)getModel();
      if (model.isSortable(modelIndex)) {
         // toggle ascension, if already sorted
         if (sortedColumnIndex == index) {
            sortedColumnAscending = !sortedColumnAscending;
         }
         sortedColumnIndex = index;
         model.sortColumn(modelIndex, sortedColumnAscending);
      }
   }
   public void mousePressed(MouseEvent event) {}
   public void mouseClicked(MouseEvent event) {}
   public void mouseEntered(MouseEvent event) {}
   public void mouseExited(MouseEvent event) {}
}
/*

  DefaultSortTableModel.java
  Created by Claude Duguay
  Copyright (c) 2002
   This was taken from a Java Pro magazine article
   http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
   I have NOT asked for permission to use this.

*/

 class DefaultSortTableModel  extends DefaultTableModel
                                    implements SortTableModel {
   public DefaultSortTableModel() {}
   public DefaultSortTableModel(int rows, int cols) {
      super(rows, cols);
   }
   public DefaultSortTableModel(Object[][] data, Object[] names) {
      super(data, names);
   }
   public DefaultSortTableModel(Object[] names, int rows) {
      super(names, rows);
   }
   public DefaultSortTableModel(Vector names, int rows) {
      super(names, rows);
   }
   public DefaultSortTableModel(Vector data, Vector names) {
      super(data, names);
   }
   public boolean isSortable(int col) {
      return true;
   }
   public void sortColumn(int col, boolean ascending) {
      Collections.sort(getDataVector(),
         new ColumnComparator(col, ascending));
   }
}
 /*
 
   SortTableModel.java
   Created by Claude Duguay
   Copyright (c) 2002
    This was taken from a Java Pro magazine article
    http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
    I have NOT asked for permission to use this.
 
 */
  interface SortTableModel extends TableModel {
    public boolean isSortable(int col);
    public void sortColumn(int col, boolean ascending);
 }
  /*
  
    ColumnComparator.java
    Created by Claude Duguay
    Copyright (c) 2002
     This was taken from a Java Pro magazine article
     http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
     I have NOT asked for permission to use this.
  
  */
   class ColumnComparator implements Comparator {
     protected int index;
     protected boolean ascending;
     public ColumnComparator(int index, boolean ascending) {
        this.index = index;
        this.ascending = ascending;
     }
     public int compare(Object one, Object two) {
        if (one instanceof Vector && two instanceof Vector) {
           Vector vOne = (Vector)one;
           Vector vTwo = (Vector)two;
           Object oOne = vOne.elementAt(index);
           Object oTwo = vTwo.elementAt(index);
           if (oOne instanceof Comparable && oTwo instanceof Comparable) {
              Comparable cOne = (Comparable)oOne;
              Comparable cTwo = (Comparable)oTwo;
              if (ascending) {
                 return cOne.rupareTo(cTwo);
              }
              else {
                 return cTwo.rupareTo(cOne);
              }
           }
        }
        return 1;
     }
  }



   /*
   
     SortHeaderRenderer.java
     Created by Claude Duguay
     Copyright (c) 2002
      This was taken from a Java Pro magazine article
      http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
      I have NOT asked for permission to use this.
   
   */
    class SortHeaderRenderer extends DefaultTableCellRenderer {
      public static Icon NONSORTED =  new SortArrowIcon(SortArrowIcon.NONE);
      public static Icon ASCENDING =  new SortArrowIcon(SortArrowIcon.ASCENDING);
      public static Icon DECENDING =  new SortArrowIcon(SortArrowIcon.DECENDING);
      public SortHeaderRenderer() {
         setHorizontalTextPosition(LEFT);
         setHorizontalAlignment(CENTER);
      }
      public Component getTableCellRendererComponent( JTable table,
                                 Object value,
                                 boolean isSelected,
                                 boolean hasFocus, int row, int col) {
         int index = -1;
         boolean ascending = true;
         if (table instanceof JSortTable) {
            JSortTable sortTable = (JSortTable)table;
            index = sortTable.getSortedColumnIndex();
            ascending = sortTable.isSortedColumnAscending();
         }
         if (table != null) {
            JTableHeader header = table.getTableHeader();
            if (header != null) {
               setForeground(header.getForeground());
               setBackground(header.getBackground());
               setFont(header.getFont());
            }
         }
         Icon icon = ascending ? ASCENDING : DECENDING;
         setIcon(col == index ? icon : NONSORTED);
         setText((value == null) ? "" : value.toString());
         setBorder(UIManager.getBorder("TableHeader.cellBorder"));
         return this;
      }
   }

    /*
    
      SortArrowIcon.java
      Created by Claude Duguay
      Copyright (c) 2002
       This was taken from a Java Pro magazine article
       http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
       I have NOT asked for permission to use this.
    
    */
    class SortArrowIcon implements Icon {
       public static final int NONE = 0;
       public static final int DECENDING = 1;
       public static final int ASCENDING = 2;
       protected int direction;
       protected int width = 8;
       protected int height = 8;
       public SortArrowIcon(int direction) {
          this.direction = direction;
       }
       public int getIconWidth() {
          return width;
       }
       public int getIconHeight() {
          return height;
       }
       public void paintIcon(Component c, Graphics g, int x, int y) {
          Color bg = c.getBackground();
          Color light = bg.brighter();
          Color shade = bg.darker();
          int w = width;
          int h = height;
          int m = w / 2;
          if (direction == ASCENDING) {
             g.setColor(shade);
             g.drawLine(x, y, x + w, y);
             g.drawLine(x, y, x + m, y + h);
             g.setColor(light);
             g.drawLine(x + w, y, x + m, y + h);
          }
          if (direction == DECENDING) {
             g.setColor(shade);
             g.drawLine(x + m, y, x, y + h);
             g.setColor(light);
             g.drawLine(x, y + h, x + w, y + h);
             g.drawLine(x + m, y, x + w, y + h);
          }
       }
    }





Mixed Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
 * (swing1.1beta3)
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
/**
 * @version 1.0 11/22/98
 */
public class MixedExample extends JFrame {
  public MixedExample() {
    super("Mixed Example");
    AttributiveCellTableModel ml = new AttributiveCellTableModel(20, 5) {
      public Object getValueAt(int row, int col) {
        return "" + row + "," + col;
      }
    };
    CellAttribute cellAtt = ml.getCellAttribute();
    MultiSpanCellTable table = new MultiSpanCellTable(ml);
    table.setCellSelectionEnabled(true);
    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    table.setDefaultRenderer(Object.class, new AttributiveCellRenderer());
    JScrollPane scroll = new JScrollPane(table);
    ColorPanel colorPanel = new ColorPanel(table, (ColoredCell) cellAtt);
    FontPanel fontPanel = new FontPanel(table, (CellFont) cellAtt);
    SpanPanel spanPanel = new SpanPanel(table, (CellSpan) cellAtt);
    Box boxAtt = new Box(BoxLayout.Y_AXIS);
    boxAtt.add(colorPanel);
    boxAtt.add(fontPanel);
    boxAtt.add(spanPanel);
    Box box = new Box(BoxLayout.X_AXIS);
    box.add(scroll);
    box.add(new JSeparator(SwingConstants.HORIZONTAL));
    box.add(boxAtt);
    getContentPane().add(box);
    setSize(400, 300);
    setVisible(true);
  }
  class ColorPanel extends JPanel {
    JTable table;
    ColoredCell cellAtt;
    ColorPanel(final JTable table, final ColoredCell cellAtt) {
      this.table = table;
      this.cellAtt = cellAtt;
      setLayout(new GridLayout(2, 1));
      setBorder(BorderFactory.createTitledBorder("Color"));
      JButton b_fore = new JButton("Foreground");
      b_fore.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          changeColor(true);
        }
      });
      JButton b_back = new JButton("Background");
      b_back.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          changeColor(false);
        }
      });
      JPanel p_buttons = new JPanel();
      add(b_fore);
      add(b_back);
    }
    private final void changeColor(boolean isForeground) {
      int[] columns = table.getSelectedColumns();
      int[] rows = table.getSelectedRows();
      if ((rows == null) || (columns == null))
        return;
      if ((rows.length < 1) || (columns.length < 1))
        return;
      Color target = cellAtt.getForeground(rows[0], columns[0]);
      Color reference = cellAtt.getBackground(rows[0], columns[0]);
      for (int i = 0; i < rows.length; i++) {
        int row = rows[i];
        for (int j = 0; j < columns.length; j++) {
          int column = columns[j];
          target = (target != cellAtt.getForeground(row, column)) ? null
              : target;
          reference = (reference != cellAtt
              .getBackground(row, column)) ? null : reference;
        }
      }
      String title;
      if (isForeground) {
        target = (target != null) ? target : table.getForeground();
        reference = (reference != null) ? reference : table
            .getBackground();
        title = "Foreground Color";
      } else {
        target = (reference != null) ? reference : table
            .getBackground();
        reference = (target != null) ? target : table.getForeground();
        title = "Foreground Color";
      }
      TextColorChooser chooser = new TextColorChooser(target, reference,
          isForeground);
      Color color = chooser.showDialog(MixedExample.this, title);
      if (color != null) {
        if (isForeground) {
          cellAtt.setForeground(color, rows, columns);
        } else {
          cellAtt.setBackground(color, rows, columns);
        }
        table.clearSelection();
        table.revalidate();
        table.repaint();
      }
    }
  }
  class FontPanel extends JPanel {
    String[] str_size = { "10", "12", "14", "16", "20" };
    String[] str_style = { "PLAIN", "BOLD", "ITALIC" };
    JComboBox name, style, size;
    FontPanel(final JTable table, final CellFont cellAtt) {
      setLayout(new BorderLayout());
      setBorder(BorderFactory.createTitledBorder("Font"));
      Box box = new Box(BoxLayout.X_AXIS);
      JPanel p2 = new JPanel(new GridLayout(3, 1));
      JPanel p3 = new JPanel(new GridLayout(3, 1));
      JPanel p4 = new JPanel(new BorderLayout());
      p2.add(new JLabel("Name:"));
      p2.add(new JLabel("Style:"));
      p2.add(new JLabel("Size:"));
      Toolkit toolkit = Toolkit.getDefaultToolkit();
      name = new JComboBox(toolkit.getFontList());
      style = new JComboBox(str_style);
      size = new JComboBox(str_size);
      size.setEditable(true);
      JButton b_apply = new JButton("Apply");
      b_apply.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          int[] columns = table.getSelectedColumns();
          int[] rows = table.getSelectedRows();
          if ((rows == null) || (columns == null))
            return;
          if ((rows.length < 1) || (columns.length < 1))
            return;
          Font font = new Font((String) name.getSelectedItem(), style
              .getSelectedIndex(), Integer.parseInt((String) size
              .getSelectedItem()));
          cellAtt.setFont(font, rows, columns);
          table.clearSelection();
          table.revalidate();
          table.repaint();
        }
      });
      p3.add(name);
      p3.add(style);
      p3.add(size);
      p4.add(BorderLayout.CENTER, b_apply);
      box.add(p2);
      box.add(p3);
      add(BorderLayout.CENTER, box);
      add(BorderLayout.SOUTH, p4);
    }
  }
  class SpanPanel extends JPanel {
    JTable table;
    CellSpan cellAtt;
    SpanPanel(final JTable table, final CellSpan cellAtt) {
      this.table = table;
      this.cellAtt = cellAtt;
      setLayout(new GridLayout(2, 1));
      setBorder(BorderFactory.createTitledBorder("Span"));
      JButton b_one = new JButton("Combine");
      b_one.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          int[] columns = table.getSelectedColumns();
          int[] rows = table.getSelectedRows();
          cellAtt.rubine(rows, columns);
          table.clearSelection();
          table.revalidate();
          table.repaint();
        }
      });
      JButton b_split = new JButton("Split");
      b_split.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          int column = table.getSelectedColumn();
          int row = table.getSelectedRow();
          cellAtt.split(row, column);
          table.clearSelection();
          table.revalidate();
          table.repaint();
        }
      });
      add(b_one);
      add(b_split);
    }
  }
  public static void main(String[] args) {
    MixedExample frame = new MixedExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
class AttributiveCellTableModel extends DefaultTableModel {
  protected CellAttribute cellAtt;
  public AttributiveCellTableModel() {
    this((Vector) null, 0);
  }
  public AttributiveCellTableModel(int numRows, int numColumns) {
    Vector names = new Vector(numColumns);
    names.setSize(numColumns);
    setColumnIdentifiers(names);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows, numColumns);
  }
  public AttributiveCellTableModel(Vector columnNames, int numRows) {
    setColumnIdentifiers(columnNames);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
  }
  public AttributiveCellTableModel(Object[] columnNames, int numRows) {
    this(convertToVector(columnNames), numRows);
  }
  public AttributiveCellTableModel(Vector data, Vector columnNames) {
    setDataVector(data, columnNames);
  }
  public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
    setDataVector(data, columnNames);
  }
  public void setDataVector(Vector newData, Vector columnNames) {
    if (newData == null)
      throw new IllegalArgumentException(
          "setDataVector() - Null parameter");
    dataVector = new Vector(0);
    setColumnIdentifiers(columnNames);
    dataVector = newData;
    //
    cellAtt = new DefaultCellAttribute(dataVector.size(), columnIdentifiers
        .size());
    newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public void addColumn(Object columnName, Vector columnData) {
    if (columnName == null)
      throw new IllegalArgumentException("addColumn() - null parameter");
    columnIdentifiers.addElement(columnName);
    int index = 0;
    Enumeration enumeration = dataVector.elements();
    while (enumeration.hasMoreElements()) {
      Object value;
      if ((columnData != null) && (index < columnData.size()))
        value = columnData.elementAt(index);
      else
        value = null;
      ((Vector) enumeration.nextElement()).addElement(value);
      index++;
    }
    //
    cellAtt.addColumn();
    fireTableStructureChanged();
  }
  public void addRow(Vector rowData) {
    Vector newData = null;
    if (rowData == null) {
      newData = new Vector(getColumnCount());
    } else {
      rowData.setSize(getColumnCount());
    }
    dataVector.addElement(newData);
    //
    cellAtt.addRow();
    newRowsAdded(new TableModelEvent(this, getRowCount() - 1,
        getRowCount() - 1, TableModelEvent.ALL_COLUMNS,
        TableModelEvent.INSERT));
  }
  public void insertRow(int row, Vector rowData) {
    if (rowData == null) {
      rowData = new Vector(getColumnCount());
    } else {
      rowData.setSize(getColumnCount());
    }
    dataVector.insertElementAt(rowData, row);
    //
    cellAtt.insertRow(row);
    newRowsAdded(new TableModelEvent(this, row, row,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public CellAttribute getCellAttribute() {
    return cellAtt;
  }
  public void setCellAttribute(CellAttribute newCellAtt) {
    int numColumns = getColumnCount();
    int numRows = getRowCount();
    if ((newCellAtt.getSize().width != numColumns)
        || (newCellAtt.getSize().height != numRows)) {
      newCellAtt.setSize(new Dimension(numRows, numColumns));
    }
    cellAtt = newCellAtt;
    fireTableDataChanged();
  }
  /*
   * public void changeCellAttribute(int row, int column, Object command) {
   * cellAtt.changeAttribute(row, column, command); }
   * 
   * public void changeCellAttribute(int[] rows, int[] columns, Object
   * command) { cellAtt.changeAttribute(rows, columns, command); }
   */
}
class DefaultCellAttribute
//implements CellAttribute ,CellSpan {
    implements CellAttribute, CellSpan, ColoredCell, CellFont {
  //
  // !!!! CAUTION !!!!!
  // these values must be synchronized to Table data
  //
  protected int rowSize;
  protected int columnSize;
  protected int[][][] span; // CellSpan
  protected Color[][] foreground; // ColoredCell
  protected Color[][] background; //
  protected Font[][] font; // CellFont
  public DefaultCellAttribute() {
    this(1, 1);
  }
  public DefaultCellAttribute(int numRows, int numColumns) {
    setSize(new Dimension(numColumns, numRows));
  }
  protected void initValue() {
    for (int i = 0; i < span.length; i++) {
      for (int j = 0; j < span[i].length; j++) {
        span[i][j][CellSpan.COLUMN] = 1;
        span[i][j][CellSpan.ROW] = 1;
      }
    }
  }
  //
  // CellSpan
  //
  public int[] getSpan(int row, int column) {
    if (isOutOfBounds(row, column)) {
      int[] ret_code = { 1, 1 };
      return ret_code;
    }
    return span[row][column];
  }
  public void setSpan(int[] span, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    this.span[row][column] = span;
  }
  public boolean isVisible(int row, int column) {
    if (isOutOfBounds(row, column))
      return false;
    if ((span[row][column][CellSpan.COLUMN] < 1)
        || (span[row][column][CellSpan.ROW] < 1))
      return false;
    return true;
  }
  public void combine(int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    int rowSpan = rows.length;
    int columnSpan = columns.length;
    int startRow = rows[0];
    int startColumn = columns[0];
    for (int i = 0; i < rowSpan; i++) {
      for (int j = 0; j < columnSpan; j++) {
        if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
            || (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
          //System.out.println("can"t combine");
          return;
        }
      }
    }
    for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
      for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
        span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
        span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
        //System.out.println("r " +ii +" c " +jj);
      }
    }
    span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
    span[startRow][startColumn][CellSpan.ROW] = rowSpan;
  }
  public void split(int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    int columnSpan = span[row][column][CellSpan.COLUMN];
    int rowSpan = span[row][column][CellSpan.ROW];
    for (int i = 0; i < rowSpan; i++) {
      for (int j = 0; j < columnSpan; j++) {
        span[row + i][column + j][CellSpan.COLUMN] = 1;
        span[row + i][column + j][CellSpan.ROW] = 1;
      }
    }
  }
  //
  // ColoredCell
  //
  public Color getForeground(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return foreground[row][column];
  }
  public void setForeground(Color color, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    foreground[row][column] = color;
  }
  public void setForeground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(foreground, color, rows, columns);
  }
  public Color getBackground(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return background[row][column];
  }
  public void setBackground(Color color, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    background[row][column] = color;
  }
  public void setBackground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(background, color, rows, columns);
  }
  //
  //
  // CellFont
  //
  public Font getFont(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return font[row][column];
  }
  public void setFont(Font font, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    this.font[row][column] = font;
  }
  public void setFont(Font font, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(this.font, font, rows, columns);
  }
  //
  //
  // CellAttribute
  //
  public void addColumn() {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows][numColumns + 1][2];
    System.arraycopy(oldSpan, 0, span, 0, numRows);
    for (int i = 0; i < numRows; i++) {
      span[i][numColumns][CellSpan.COLUMN] = 1;
      span[i][numColumns][CellSpan.ROW] = 1;
    }
  }
  public void addRow() {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    System.arraycopy(oldSpan, 0, span, 0, numRows);
    for (int i = 0; i < numColumns; i++) {
      span[numRows][i][CellSpan.COLUMN] = 1;
      span[numRows][i][CellSpan.ROW] = 1;
    }
  }
  public void insertRow(int row) {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    if (0 < row) {
      System.arraycopy(oldSpan, 0, span, 0, row - 1);
    }
    System.arraycopy(oldSpan, 0, span, row, numRows - row);
    for (int i = 0; i < numColumns; i++) {
      span[row][i][CellSpan.COLUMN] = 1;
      span[row][i][CellSpan.ROW] = 1;
    }
  }
  public Dimension getSize() {
    return new Dimension(rowSize, columnSize);
  }
  public void setSize(Dimension size) {
    columnSize = size.width;
    rowSize = size.height;
    span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
    foreground = new Color[rowSize][columnSize];
    background = new Color[rowSize][columnSize];
    font = new Font[rowSize][columnSize];
    initValue();
  }
  /*
   * public void changeAttribute(int row, int column, Object command) { }
   * 
   * public void changeAttribute(int[] rows, int[] columns, Object command) { }
   */
  protected boolean isOutOfBounds(int row, int column) {
    if ((row < 0) || (rowSize <= row) || (column < 0)
        || (columnSize <= column)) {
      return true;
    }
    return false;
  }
  protected boolean isOutOfBounds(int[] rows, int[] columns) {
    for (int i = 0; i < rows.length; i++) {
      if ((rows[i] < 0) || (rowSize <= rows[i]))
        return true;
    }
    for (int i = 0; i < columns.length; i++) {
      if ((columns[i] < 0) || (columnSize <= columns[i]))
        return true;
    }
    return false;
  }
  protected void setValues(Object[][] target, Object value, int[] rows,
      int[] columns) {
    for (int i = 0; i < rows.length; i++) {
      int row = rows[i];
      for (int j = 0; j < columns.length; j++) {
        int column = columns[j];
        target[row][column] = value;
      }
    }
  }
}
interface CellAttribute {
  public void addColumn();
  public void addRow();
  public void insertRow(int row);
  public Dimension getSize();
  public void setSize(Dimension size);
}
interface ColoredCell {
  public Color getForeground(int row, int column);
  public void setForeground(Color color, int row, int column);
  public void setForeground(Color color, int[] rows, int[] columns);
  public Color getBackground(int row, int column);
  public void setBackground(Color color, int row, int column);
  public void setBackground(Color color, int[] rows, int[] columns);
}
interface CellFont {
  public Font getFont(int row, int column);
  public void setFont(Font font, int row, int column);
  public void setFont(Font font, int[] rows, int[] columns);
}
interface CellSpan {
  public final int ROW = 0;
  public final int COLUMN = 1;
  public int[] getSpan(int row, int column);
  public void setSpan(int[] span, int row, int column);
  public boolean isVisible(int row, int column);
  public void combine(int[] rows, int[] columns);
  public void split(int row, int column);
}
class MultiSpanCellTable extends JTable {
  public MultiSpanCellTable(TableModel model) {
    super(model);
    setUI(new MultiSpanCellTableUI());
    getTableHeader().setReorderingAllowed(false);
    setCellSelectionEnabled(true);
    setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
  }
  public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
    Rectangle sRect = super.getCellRect(row, column, includeSpacing);
    if ((row < 0) || (column < 0) || (getRowCount() <= row)
        || (getColumnCount() <= column)) {
      return sRect;
    }
    CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel())
        .getCellAttribute();
    if (!cellAtt.isVisible(row, column)) {
      int temp_row = row;
      int temp_column = column;
      row += cellAtt.getSpan(temp_row, temp_column)[CellSpan.ROW];
      column += cellAtt.getSpan(temp_row, temp_column)[CellSpan.COLUMN];
    }
    int[] n = cellAtt.getSpan(row, column);
    int index = 0;
    int columnMargin = getColumnModel().getColumnMargin();
    Rectangle cellFrame = new Rectangle();
    int aCellHeight = rowHeight + rowMargin;
    cellFrame.y = row * aCellHeight;
    cellFrame.height = n[CellSpan.ROW] * aCellHeight;
    Enumeration enumeration = getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
      TableColumn aColumn = (TableColumn) enumeration.nextElement();
      cellFrame.width = aColumn.getWidth() + columnMargin;
      if (index == column)
        break;
      cellFrame.x += cellFrame.width;
      index++;
    }
    for (int i = 0; i < n[CellSpan.COLUMN] - 1; i++) {
      TableColumn aColumn = (TableColumn) enumeration.nextElement();
      cellFrame.width += aColumn.getWidth() + columnMargin;
    }
    if (!includeSpacing) {
      Dimension spacing = getIntercellSpacing();
      cellFrame.setBounds(cellFrame.x + spacing.width / 2, cellFrame.y
          + spacing.height / 2, cellFrame.width - spacing.width,
          cellFrame.height - spacing.height);
    }
    return cellFrame;
  }
  private int[] rowColumnAtPoint(Point point) {
    int[] retValue = { -1, -1 };
    int row = point.y / (rowHeight + rowMargin);
    if ((row < 0) || (getRowCount() <= row))
      return retValue;
    int column = getColumnModel().getColumnIndexAtX(point.x);
    CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel())
        .getCellAttribute();
    if (cellAtt.isVisible(row, column)) {
      retValue[CellSpan.COLUMN] = column;
      retValue[CellSpan.ROW] = row;
      return retValue;
    }
    retValue[CellSpan.COLUMN] = column
        + cellAtt.getSpan(row, column)[CellSpan.COLUMN];
    retValue[CellSpan.ROW] = row
        + cellAtt.getSpan(row, column)[CellSpan.ROW];
    return retValue;
  }
  public int rowAtPoint(Point point) {
    return rowColumnAtPoint(point)[CellSpan.ROW];
  }
  public int columnAtPoint(Point point) {
    return rowColumnAtPoint(point)[CellSpan.COLUMN];
  }
  public void columnSelectionChanged(ListSelectionEvent e) {
    repaint();
  }
  public void valueChanged(ListSelectionEvent e) {
    int firstIndex = e.getFirstIndex();
    int lastIndex = e.getLastIndex();
    if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
      repaint();
    }
    Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
    int numCoumns = getColumnCount();
    int index = firstIndex;
    for (int i = 0; i < numCoumns; i++) {
      dirtyRegion.add(getCellRect(index, i, false));
    }
    index = lastIndex;
    for (int i = 0; i < numCoumns; i++) {
      dirtyRegion.add(getCellRect(index, i, false));
    }
    repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width,
        dirtyRegion.height);
  }
}
class MultiSpanCellTableUI extends BasicTableUI {
  public void paint(Graphics g, JComponent c) {
    Rectangle oldClipBounds = g.getClipBounds();
    Rectangle clipBounds = new Rectangle(oldClipBounds);
    int tableWidth = table.getColumnModel().getTotalColumnWidth();
    clipBounds.width = Math.min(clipBounds.width, tableWidth);
    g.setClip(clipBounds);
    int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y));
    int lastIndex = table.getRowCount() - 1;
    Rectangle rowRect = new Rectangle(0, 0, tableWidth, table
        .getRowHeight()
        + table.getRowMargin());
    rowRect.y = firstIndex * rowRect.height;
    for (int index = firstIndex; index <= lastIndex; index++) {
      if (rowRect.intersects(clipBounds)) {
        //System.out.println(); // debug
        //System.out.print("" + index +": "); // row
        paintRow(g, index);
      }
      rowRect.y += rowRect.height;
    }
    g.setClip(oldClipBounds);
  }
  private void paintRow(Graphics g, int row) {
    Rectangle rect = g.getClipBounds();
    boolean drawn = false;
    AttributiveCellTableModel tableModel = (AttributiveCellTableModel) table
        .getModel();
    CellSpan cellAtt = (CellSpan) tableModel.getCellAttribute();
    int numColumns = table.getColumnCount();
    for (int column = 0; column < numColumns; column++) {
      Rectangle cellRect = table.getCellRect(row, column, true);
      int cellRow, cellColumn;
      if (cellAtt.isVisible(row, column)) {
        cellRow = row;
        cellColumn = column;
        //  System.out.print(" "+column+" "); // debug
      } else {
        cellRow = row + cellAtt.getSpan(row, column)[CellSpan.ROW];
        cellColumn = column
            + cellAtt.getSpan(row, column)[CellSpan.COLUMN];
        //  System.out.print(" ("+column+")"); // debug
      }
      if (cellRect.intersects(rect)) {
        drawn = true;
        paintCell(g, cellRect, cellRow, cellColumn);
      } else {
        if (drawn)
          break;
      }
    }
  }
  private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
    int spacingHeight = table.getRowMargin();
    int spacingWidth = table.getColumnModel().getColumnMargin();
    Color c = g.getColor();
    g.setColor(table.getGridColor());
    g.drawRect(cellRect.x, cellRect.y, cellRect.width - 1,
        cellRect.height - 1);
    g.setColor(c);
    cellRect.setBounds(cellRect.x + spacingWidth / 2, cellRect.y
        + spacingHeight / 2, cellRect.width - spacingWidth,
        cellRect.height - spacingHeight);
    if (table.isEditing() && table.getEditingRow() == row
        && table.getEditingColumn() == column) {
      Component component = table.getEditorComponent();
      component.setBounds(cellRect);
      component.validate();
    } else {
      TableCellRenderer renderer = table.getCellRenderer(row, column);
      Component component = table.prepareRenderer(renderer, row, column);
      if (component.getParent() == null) {
        rendererPane.add(component);
      }
      rendererPane.paintComponent(g, component, table, cellRect.x,
          cellRect.y, cellRect.width, cellRect.height, true);
    }
  }
}
class AttributiveCellRenderer extends JLabel implements TableCellRenderer {
  protected static Border noFocusBorder;
  public AttributiveCellRenderer() {
    noFocusBorder = new EmptyBorder(1, 2, 1, 2);
    setOpaque(true);
    setBorder(noFocusBorder);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    Color foreground = null;
    Color background = null;
    Font font = null;
    TableModel model = table.getModel();
    if (model instanceof AttributiveCellTableModel) {
      CellAttribute cellAtt = ((AttributiveCellTableModel) model)
          .getCellAttribute();
      if (cellAtt instanceof ColoredCell) {
        foreground = ((ColoredCell) cellAtt).getForeground(row, column);
        background = ((ColoredCell) cellAtt).getBackground(row, column);
      }
      if (cellAtt instanceof CellFont) {
        font = ((CellFont) cellAtt).getFont(row, column);
      }
    }
    if (isSelected) {
      setForeground((foreground != null) ? foreground : table
          .getSelectionForeground());
      setBackground(table.getSelectionBackground());
    } else {
      setForeground((foreground != null) ? foreground : table
          .getForeground());
      setBackground((background != null) ? background : table
          .getBackground());
    }
    setFont((font != null) ? font : table.getFont());
    if (hasFocus) {
      setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      if (table.isCellEditable(row, column)) {
        setForeground((foreground != null) ? foreground : UIManager
            .getColor("Table.focusCellForeground"));
        setBackground(UIManager.getColor("Table.focusCellBackground"));
      }
    } else {
      setBorder(noFocusBorder);
    }
    setValue(value);
    return this;
  }
  protected void setValue(Object value) {
    setText((value == null) ? "" : value.toString());
  }
}
class TextPreviewLabel extends JLabel {
  private String sampleText = "  Sample Text  Sample Text  ";
  boolean isForgroundSelection;
  public TextPreviewLabel() {
    this(Color.black, Color.white, true);
  }
  public TextPreviewLabel(Color fore, Color back, boolean isForgroundSelection) {
    setOpaque(true);
    setForeground(fore);
    setBackground(back);
    this.isForgroundSelection = isForgroundSelection;
    setText(sampleText);
  }
  public void setForeground(Color col) {
    if (isForgroundSelection) {
      super.setForeground(col);
    } else {
      super.setBackground(col);
    }
  }
}
class ColorChooserDialog extends JDialog {
  private Color initialColor;
  private Color retColor;
  private JColorChooser chooserPane;
  public ColorChooserDialog(Component c, String title,
      final JColorChooser chooserPane) {
    super(JOptionPane.getFrameForComponent(c), title, true);
    setResizable(false);
    this.chooserPane = chooserPane;
    String okString = UIManager.getString("ColorChooser.okText");
    String cancelString = UIManager.getString("ColorChooser.cancelText");
    String resetString = UIManager.getString("ColorChooser.resetText");
    Container contentPane = getContentPane();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(chooserPane, BorderLayout.CENTER);
    JPanel buttonPane = new JPanel();
    buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
    JButton okButton = new JButton(okString);
    getRootPane().setDefaultButton(okButton);
    okButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        retColor = chooserPane.getColor();
        setVisible(false);
      }
    });
    buttonPane.add(okButton);
    JButton cancelButton = new JButton(cancelString);
    cancelButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        retColor = null;
        setVisible(false);
      }
    });
    buttonPane.add(cancelButton);
    JButton resetButton = new JButton(resetString);
    resetButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chooserPane.setColor(initialColor);
      }
    });
    buttonPane.add(resetButton);
    contentPane.add(buttonPane, BorderLayout.SOUTH);
    pack();
    setLocationRelativeTo(c);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        setVisible(false);
      }
    });
  }
  public Color getColor() {
    return retColor;
  }
}
class TextColorChooser extends JColorChooser {
  public TextColorChooser(Color target, Color reference,
      boolean isForgroundSelection) {
    super(target);
    if (isForgroundSelection) {
      setPreviewPanel(new TextPreviewLabel(target, reference,
          isForgroundSelection));
    } else {
      setPreviewPanel(new TextPreviewLabel(reference, target,
          isForgroundSelection));
    }
    updateUI();
  }
  public Color showDialog(Component component, String title) {
    ColorChooserDialog dialog = new ColorChooserDialog(component, title,
        this);
    dialog.show();
    Color col = dialog.getColor();
    dialog.dispose();
    return col;
  }
}





MultiLine Cell Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
 * If You can accept all cells have same Height.
 */
/* (swing1.1beta3) */
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
 * @version 1.0 11/09/98
 */
public class MultiLineCellExample extends JFrame {
  MultiLineCellExample() {
    super("Multi-Line Cell Example");
    DefaultTableModel dm = new DefaultTableModel() {
      public Class getColumnClass(int columnIndex) {
        return String.class;
      }
    };
    dm.setDataVector(new Object[][] { { "a\na", "b\nb", "c\nc" },
        { "A\nA", "B\nB", "C\nC" } }, new Object[] { "1", "2", "3" });
    JTable table = new JTable(dm);
    int lines = 2;
    table.setRowHeight(table.getRowHeight() * lines);
    //
    // table.setRowHeight(0);
    //
    // I got "java.lang.IllegalArgumentException: New row height less than
    // 1"
    //
    table.setDefaultRenderer(String.class, new MultiLineCellRenderer());
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll);
    setSize(400, 130);
    setVisible(true);
  }
  public static void main(String[] args) {
    MultiLineCellExample frame = new MultiLineCellExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
/**
 * @version 1.0 11/09/98
 */
class MultiLineCellRenderer extends JTextArea implements TableCellRenderer {
  public MultiLineCellRenderer() {
    setLineWrap(true);
    setWrapStyleWord(true);
    setOpaque(true);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    if (isSelected) {
      setForeground(table.getSelectionForeground());
      setBackground(table.getSelectionBackground());
    } else {
      setForeground(table.getForeground());
      setBackground(table.getBackground());
    }
    setFont(table.getFont());
    if (hasFocus) {
      setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      if (table.isCellEditable(row, column)) {
        setForeground(UIManager.getColor("Table.focusCellForeground"));
        setBackground(UIManager.getColor("Table.focusCellBackground"));
      }
    } else {
      setBorder(new EmptyBorder(1, 2, 1, 2));
    }
    setText((value == null) ? "" : value.toString());
    return this;
  }
}





MultiLine Header Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
/**
 * @version 1.0 11/09/98
 */
public class MultiLineHeaderExample extends JFrame {
  MultiLineHeaderExample() {
    super("Multi-Line Header Example");
    DefaultTableModel dm = new DefaultTableModel();
    dm.setDataVector(
        new Object[][] { { "a", "b", "c" }, { "A", "B", "C" } },
        new Object[] { "1st\nalpha", "2nd\nbeta", "3rd\ngamma" });
    JTable table = new JTable(dm);
    MultiLineHeaderRenderer renderer = new MultiLineHeaderRenderer();
    Enumeration e = table.getColumnModel().getColumns();
    while (e.hasMoreElements()) {
      ((TableColumn) e.nextElement()).setHeaderRenderer(renderer);
    }
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll);
    setSize(400, 110);
    setVisible(true);
  }
  public static void main(String[] args) {
    MultiLineHeaderExample frame = new MultiLineHeaderExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
/**
 * @version 1.0 11/09/98
 */
class MultiLineHeaderRenderer extends JList implements TableCellRenderer {
  public MultiLineHeaderRenderer() {
    setOpaque(true);
    setForeground(UIManager.getColor("TableHeader.foreground"));
    setBackground(UIManager.getColor("TableHeader.background"));
    setBorder(UIManager.getBorder("TableHeader.cellBorder"));
    ListCellRenderer renderer = getCellRenderer();
    ((JLabel) renderer).setHorizontalAlignment(JLabel.CENTER);
    setCellRenderer(renderer);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    setFont(table.getFont());
    String str = (value == null) ? "" : value.toString();
    BufferedReader br = new BufferedReader(new StringReader(str));
    String line;
    Vector v = new Vector();
    try {
      while ((line = br.readLine()) != null) {
        v.addElement(line);
      }
    } catch (IOException ex) {
      ex.printStackTrace();
    }
    setListData(v);
    return this;
  }
}





MultiLine Header Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class MultiLineHeaderTable {
  
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Multi-line Header Table");
    JTable tbl = new JTable(new CurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tcm.getColumn(1).setPreferredWidth(100);
    tcm.getColumn(1).setMinWidth(100);
    // Add the stripe renderer.
    StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
        Color.white, null, null);
    // Add the custom header renderer
    MultiLineHeaderRenderer headerRenderer = new MultiLineHeaderRenderer(
        SwingConstants.CENTER, SwingConstants.BOTTOM);
    headerRenderer.setBackground(Color.blue);
    headerRenderer.setForeground(Color.white);
    headerRenderer.setFont(new Font("Dialog", Font.BOLD, 12));
    int columns = tableHeaders.length;
    for (int i = 0; i < columns; i++) {
      tcm.getColumn(i).setHeaderRenderer(headerRenderer);
      tcm.getColumn(i).setHeaderValue(tableHeaders[i]);
    }
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
  // Header values. Note the table model provides
  // string column names that are the default header
  // values.
  public static Object[][] tableHeaders = new Object[][] {
      new String[] { "Currency" },
      new String[] { "Yesterday"s", "Rate" },
      new String[] { "Today"s", "Rate" },
      new String[] { "Rate", "Change" } };
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon) value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}
class MultiLineHeaderRenderer extends JPanel implements TableCellRenderer {
  public MultiLineHeaderRenderer(int horizontalAlignment,
      int verticalAlignment) {
    this.horizontalAlignment = horizontalAlignment;
    this.verticalAlignment = verticalAlignment;
    switch (horizontalAlignment) {
    case SwingConstants.LEFT:
      alignmentX = (float) 0.0;
      break;
    case SwingConstants.CENTER:
      alignmentX = (float) 0.5;
      break;
    case SwingConstants.RIGHT:
      alignmentX = (float) 1.0;
      break;
    default:
      throw new IllegalArgumentException(
          "Illegal horizontal alignment value");
    }
    setBorder(headerBorder);
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    setOpaque(true);
    background = null;
  }
  public void setForeground(Color foreground) {
    this.foreground = foreground;
    super.setForeground(foreground);
  }
  public void setBackground(Color background) {
    this.background = background;
    super.setBackground(background);
  }
  public void setFont(Font font) {
    this.font = font;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    removeAll();
    invalidate();
    if (value == null) {
      // Do nothing if no value
      return this;
    }
    // Set the foreground and background colors
    // from the table header if they are not set
    if (table != null) {
      JTableHeader header = table.getTableHeader();
      if (header != null) {
        if (foreground == null) {
          super.setForeground(header.getForeground());
        }
        if (background == null) {
          super.setBackground(header.getBackground());
        }
      }
    }
    if (verticalAlignment != SwingConstants.TOP) {
      add(Box.createVerticalGlue());
    }
    Object[] values;
    int length;
    if (value instanceof Object[]) {
      // Input is an array - use it
      values = (Object[]) value;
    } else {
      // Not an array - turn it into one
      values = new Object[1];
      values[0] = value;
    }
    length = values.length;
    // Configure each row of the header using
    // a separate JLabel. If a given row is
    // a JComponent, add it directly..
    for (int i = 0; i < length; i++) {
      Object thisRow = values[i];
      if (thisRow instanceof JComponent) {
        add((JComponent) thisRow);
      } else {
        JLabel l = new JLabel();
        setValue(l, thisRow, i);
        add(l);
      }
    }
    if (verticalAlignment != SwingConstants.BOTTOM) {
      add(Box.createVerticalGlue());
    }
    return this;
  }
  // Configures a label for one line of the header.
  // This can be overridden by derived classes
  protected void setValue(JLabel l, Object value, int lineNumber) {
    if (value != null && value instanceof Icon) {
      l.setIcon((Icon) value);
    } else {
      l.setText(value == null ? "" : value.toString());
    }
    l.setHorizontalAlignment(horizontalAlignment);
    l.setAlignmentX(alignmentX);
    l.setOpaque(false);
    l.setForeground(foreground);
    l.setFont(font);
  }
  protected int verticalAlignment;
  protected int horizontalAlignment;
  protected float alignmentX;
  // These attributes may be explicitly set
  // They are defaulted to the colors and attributes
  // of the table header
  protected Color foreground;
  protected Color background;
  // These attributes have fixed defaults
  protected Border headerBorder = UIManager
      .getBorder("TableHeader.cellBorder");
  protected Font font = UIManager.getFont("TableHeader.font");
}





MultiLine Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.ruponent;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class MultiLineTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Multi-line Cell Table");
    JTable tbl = new JTable(new MultiLineTableModel());
    // Create the custom cell renderer
    MultiLineCellRenderer multiLineRenderer = new MultiLineCellRenderer(
        SwingConstants.LEFT, SwingConstants.CENTER);
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(75);
    tcm.getColumn(0).setMinWidth(75);
    tcm.getColumn(1).setPreferredWidth(150);
    tcm.getColumn(1).setMinWidth(150);
    // Install the multi-line renderer
    tcm.getColumn(0).setCellRenderer(multiLineRenderer);
    tcm.getColumn(1).setCellRenderer(multiLineRenderer);
    // Set the table row height
    tbl.setRowHeight(56);
    // Add the stripe renderer.
    StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
        Color.white, null, null);
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class MultiLineTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Flight", "Crew" };
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return 2;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected Object[][] data = new Object[][] {
      {
          "Apollo 11",
          new String[] { "Neil Armstrong", "Buzz Aldrin",
              "Michael Collins" } },
      {
          "Apollo 12",
          new String[] { "Pete Conrad", "Alan Bean", "Richard Gordon" } },
      {
          "Apollo 13",
          new String[] { "James Lovell", "Fred Haise", "Jack Swigert" } },
      {
          "Apollo 14",
          new String[] { "Alan Shepard", "Edgar Mitchell",
              "Stuart Roosa" } },
      { "Apollo 15",
          new String[] { "Dave Scott", "Jim Irwin", "Al Worden" } },
      {
          "Apollo 16",
          new String[] { "John Young", "Charlie Duke",
              "Ken Mattingly" } },
      {
          "Apollo 17",
          new String[] { "Eugene Cernan", "Harrison Schmitt",
              "Ron Evans" } } };
}
class MultiLineCellRenderer extends JPanel implements TableCellRenderer {
  public MultiLineCellRenderer(int horizontalAlignment, int verticalAlignment) {
    this.horizontalAlignment = horizontalAlignment;
    this.verticalAlignment = verticalAlignment;
    switch (horizontalAlignment) {
    case SwingConstants.LEFT:
      alignmentX = (float) 0.0;
      break;
    case SwingConstants.CENTER:
      alignmentX = (float) 0.5;
      break;
    case SwingConstants.RIGHT:
      alignmentX = (float) 1.0;
      break;
    default:
      throw new IllegalArgumentException(
          "Illegal horizontal alignment value");
    }
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    setOpaque(true);
    setBorder(border);
    background = null;
    foreground = null;
  }
  public void setForeground(Color foreground) {
    super.setForeground(foreground);
    Component[] comps = this.getComponents();
    int ncomp = comps.length;
    for (int i = 0; i < ncomp; i++) {
      Component comp = comps[i];
      if (comp instanceof JLabel) {
        comp.setForeground(foreground);
      }
    }
  }
  public void setBackground(Color background) {
    this.background = background;
    super.setBackground(background);
  }
  public void setFont(Font font) {
    this.font = font;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    removeAll();
    invalidate();
    if (value == null || table == null) {
      // Do nothing if no value
      return this;
    }
    Color cellForeground;
    Color cellBackground;
    // Set the foreground and background colors
    // from the table if they are not set
    cellForeground = (foreground == null ? table.getForeground()
        : foreground);
    cellBackground = (background == null ? table.getBackground()
        : background);
    // Handle selection and focus colors
    if (isSelected == true) {
      cellForeground = table.getSelectionForeground();
      cellBackground = table.getSelectionBackground();
    }
    if (hasFocus == true) {
      setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      if (table.isCellEditable(row, column)) {
        cellForeground = UIManager
            .getColor("Table.focusCellForeground");
        cellBackground = UIManager
            .getColor("Table.focusCellBackground");
      }
    } else {
      setBorder(border);
    }
    super.setForeground(cellForeground);
    super.setBackground(cellBackground);
    // Default the font from the table
    if (font == null) {
      font = table.getFont();
    }
    if (verticalAlignment != SwingConstants.TOP) {
      add(Box.createVerticalGlue());
    }
    Object[] values;
    int length;
    if (value instanceof Object[]) {
      // Input is an array - use it
      values = (Object[]) value;
    } else {
      // Not an array - turn it into one
      values = new Object[1];
      values[0] = value;
    }
    length = values.length;
    // Configure each row of the cell using
    // a separate JLabel. If a given row is
    // a JComponent, add it directly..
    for (int i = 0; i < length; i++) {
      Object thisRow = values[i];
      if (thisRow instanceof JComponent) {
        add((JComponent) thisRow);
      } else {
        JLabel l = new JLabel();
        setValue(l, thisRow, i, cellForeground);
        add(l);
      }
    }
    if (verticalAlignment != SwingConstants.BOTTOM) {
      add(Box.createVerticalGlue());
    }
    return this;
  }
  // Configures a label for one line of the cell.
  // This can be overridden by derived classes
  protected void setValue(JLabel l, Object value, int lineNumber,
      Color cellForeground) {
    if (value != null && value instanceof Icon) {
      l.setIcon((Icon) value);
    } else {
      l.setText(value == null ? "" : value.toString());
    }
    l.setHorizontalAlignment(horizontalAlignment);
    l.setAlignmentX(alignmentX);
    l.setOpaque(false);
    l.setForeground(cellForeground);
    l.setFont(font);
  }
  protected int verticalAlignment;
  protected int horizontalAlignment;
  protected float alignmentX;
  // These attributes may be explicitly set
  // They are defaulted to the colors and attributes
  // of the table
  protected Color foreground;
  protected Color background;
  protected Font font;
  protected static Border border = new EmptyBorder(1, 2, 1, 2);
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}





multiple Component Table 2: checkbox

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */

import java.awt.ruponent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import java.util.Hashtable;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
/**
 * @version 1.0 11/09/98
 */
class CheckBoxRenderer extends JCheckBox implements TableCellRenderer {
  CheckBoxRenderer() {
    setHorizontalAlignment(JLabel.CENTER);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    if (isSelected) {
      setForeground(table.getSelectionForeground());
      //super.setBackground(table.getSelectionBackground());
      setBackground(table.getSelectionBackground());
    } else {
      setForeground(table.getForeground());
      setBackground(table.getBackground());
    }
    setSelected((value != null && ((Boolean) value).booleanValue()));
    return this;
  }
}
public class MultiComponentTable2 extends JFrame {
  public MultiComponentTable2() {
    super("MultiComponent Table");
    DefaultTableModel dm = new DefaultTableModel() {
      public boolean isCellEditable(int row, int column) {
        if (column == 0) {
          return true;
        }
        return false;
      }
    };
    dm.setDataVector(new Object[][] {
        { "true", "String", "JLabel", "JComboBox" },
        { "false", "String", "JLabel", "JComboBox" },
        { new Boolean(true), "Boolean", "JCheckBox", "JCheckBox" },
        { new Boolean(false), "Boolean", "JCheckBox", "JCheckBox" },
        { "true", "String", "JLabel", "JTextField" },
        { "false", "String", "JLabel", "JTextField" } }, new Object[] {
        "Component", "Data", "Renderer", "Editor" });
    CheckBoxRenderer checkBoxRenderer = new CheckBoxRenderer();
    EachRowRenderer rowRenderer = new EachRowRenderer();
    rowRenderer.add(2, checkBoxRenderer);
    rowRenderer.add(3, checkBoxRenderer);
    JComboBox comboBox = new JComboBox();
    comboBox.addItem("true");
    comboBox.addItem("false");
    JCheckBox checkBox = new JCheckBox();
    checkBox.setHorizontalAlignment(JLabel.CENTER);
    DefaultCellEditor comboBoxEditor = new DefaultCellEditor(comboBox);
    DefaultCellEditor checkBoxEditor = new DefaultCellEditor(checkBox);
    JTable table = new JTable(dm);
// modified by jexp.ru
    EachRowEditor rowEditor = new EachRowEditor(table);
    rowEditor.setEditorAt(0, comboBoxEditor);
    rowEditor.setEditorAt(1, comboBoxEditor);
    rowEditor.setEditorAt(2, checkBoxEditor);
    rowEditor.setEditorAt(3, checkBoxEditor);
// end
    
    table.getColumn("Component").setCellRenderer(rowRenderer);
    table.getColumn("Component").setCellEditor(rowEditor);
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll);
    setSize(400, 160);
    setVisible(true);
  }
  public static void main(String[] args) {
    MultiComponentTable2 frame = new MultiComponentTable2();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
/**
 * @version 1.0 11/09/98
 */
class EachRowRenderer implements TableCellRenderer {
  protected Hashtable renderers;
  protected TableCellRenderer renderer, defaultRenderer;
  public EachRowRenderer() {
    renderers = new Hashtable();
    defaultRenderer = new DefaultTableCellRenderer();
  }
  public void add(int row, TableCellRenderer renderer) {
    renderers.put(new Integer(row), renderer);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    renderer = (TableCellRenderer) renderers.get(new Integer(row));
    if (renderer == null) {
      renderer = defaultRenderer;
    }
    return renderer.getTableCellRendererComponent(table, value, isSelected,
        hasFocus, row, column);
  }
}
/**
 * each row TableCellEditor
 * 
 * @version 1.1 09/09/99
 * @author Nobuo Tamemasa
 */
class EachRowEditor implements TableCellEditor {
  protected Hashtable editors;
  protected TableCellEditor editor, defaultEditor;
  JTable table;
  /**
   * Constructs a EachRowEditor. create default editor
   * 
   * @see TableCellEditor
   * @see DefaultCellEditor
   */
  public EachRowEditor(JTable table) {
    this.table = table;
    editors = new Hashtable();
    defaultEditor = new DefaultCellEditor(new JTextField());
  }
  /**
   * @param row
   *            table row
   * @param editor
   *            table cell editor
   */
  public void setEditorAt(int row, TableCellEditor editor) {
    editors.put(new Integer(row), editor);
  }
  public Component getTableCellEditorComponent(JTable table, Object value,
      boolean isSelected, int row, int column) {
    //editor = (TableCellEditor)editors.get(new Integer(row));
    //if (editor == null) {
    //  editor = defaultEditor;
    //}
    return editor.getTableCellEditorComponent(table, value, isSelected,
        row, column);
  }
  public Object getCellEditorValue() {
    return editor.getCellEditorValue();
  }
  public boolean stopCellEditing() {
    return editor.stopCellEditing();
  }
  public void cancelCellEditing() {
    editor.cancelCellEditing();
  }
  public boolean isCellEditable(EventObject anEvent) {
    selectEditor((MouseEvent) anEvent);
    return editor.isCellEditable(anEvent);
  }
  public void addCellEditorListener(CellEditorListener l) {
    editor.addCellEditorListener(l);
  }
  public void removeCellEditorListener(CellEditorListener l) {
    editor.removeCellEditorListener(l);
  }
  public boolean shouldSelectCell(EventObject anEvent) {
    selectEditor((MouseEvent) anEvent);
    return editor.shouldSelectCell(anEvent);
  }
  protected void selectEditor(MouseEvent e) {
    int row;
    if (e == null) {
      row = table.getSelectionModel().getAnchorSelectionIndex();
    } else {
      row = table.rowAtPoint(e.getPoint());
    }
    editor = (TableCellEditor) editors.get(new Integer(row));
    if (editor == null) {
      editor = defaultEditor;
    }
  }
}





Multiple Component Table: Checkbox and Combobox

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */

import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
/**
 * @version 1.0 11/09/98
 */
class ComboString {
  String str;
  ComboString(String str) {
    this.str = str;
  }
  public String toString() {
    return str;
  }
}
class MultiRenderer extends DefaultTableCellRenderer {
  JCheckBox checkBox = new JCheckBox();
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    if (value instanceof Boolean) { // Boolean
      checkBox.setSelected(((Boolean) value).booleanValue());
      checkBox.setHorizontalAlignment(JLabel.CENTER);
      return checkBox;
    }
    String str = (value == null) ? "" : value.toString();
    return super.getTableCellRendererComponent(table, str, isSelected,
        hasFocus, row, column);
  }
}
class MultiEditor implements TableCellEditor {
  private final static int COMBO = 0;
  private final static int BOOLEAN = 1;
  private final static int STRING = 2;
  private final static int NUM_EDITOR = 3;
  DefaultCellEditor[] cellEditors;
  JComboBox comboBox;
  int flg;
  public MultiEditor() {
    cellEditors = new DefaultCellEditor[NUM_EDITOR];
    comboBox = new JComboBox();
    comboBox.addItem("true");
    comboBox.addItem("false");
    cellEditors[COMBO] = new DefaultCellEditor(comboBox);
    JCheckBox checkBox = new JCheckBox();
    //checkBox.setOpaque( true );
    checkBox.setHorizontalAlignment(JLabel.CENTER);
    cellEditors[BOOLEAN] = new DefaultCellEditor(checkBox);
    JTextField textField = new JTextField();
    cellEditors[STRING] = new DefaultCellEditor(textField);
    flg = NUM_EDITOR; // nobody
  }
  public Component getTableCellEditorComponent(JTable table, Object value,
      boolean isSelected, int row, int column) {
    if (value instanceof ComboString) { // ComboString
      flg = COMBO;
      String str = (value == null) ? "" : value.toString();
      return cellEditors[COMBO].getTableCellEditorComponent(table, str,
          isSelected, row, column);
    } else if (value instanceof Boolean) { // Boolean
      flg = BOOLEAN;
      return cellEditors[BOOLEAN].getTableCellEditorComponent(table,
          value, isSelected, row, column);
    } else if (value instanceof String) { // String
      flg = STRING;
      return cellEditors[STRING].getTableCellEditorComponent(table,
          value, isSelected, row, column);
    }
    return null;
  }
  public Object getCellEditorValue() {
    switch (flg) {
    case COMBO:
      String str = (String) comboBox.getSelectedItem();
      return new ComboString(str);
    case BOOLEAN:
    case STRING:
      return cellEditors[flg].getCellEditorValue();
    default:
      return null;
    }
  }
  public Component getComponent() {
    return cellEditors[flg].getComponent();
  }
  public boolean stopCellEditing() {
    return cellEditors[flg].stopCellEditing();
  }
  public void cancelCellEditing() {
    cellEditors[flg].cancelCellEditing();
  }
  public boolean isCellEditable(EventObject anEvent) {
    return cellEditors[flg].isCellEditable(anEvent);
  }
  public boolean shouldSelectCell(EventObject anEvent) {
    return cellEditors[flg].shouldSelectCell(anEvent);
  }
  public void addCellEditorListener(CellEditorListener l) {
    cellEditors[flg].addCellEditorListener(l);
  }
  public void removeCellEditorListener(CellEditorListener l) {
    cellEditors[flg].removeCellEditorListener(l);
  }
  public void setClickCountToStart(int n) {
    cellEditors[flg].setClickCountToStart(n);
  }
  public int getClickCountToStart() {
    return cellEditors[flg].getClickCountToStart();
  }
}
public class MultiComponentTable extends JFrame {
  public MultiComponentTable() {
    super("MultiComponent Table");
    DefaultTableModel dm = new DefaultTableModel() {
      public boolean isCellEditable(int row, int column) {
        if (column == 0) {
          return true;
        }
        return false;
      }
    };
    dm.setDataVector(
        new Object[][] {
            { new ComboString("true"), "ComboString", "JLabel",
                "JComboBox" },
            { new ComboString("false"), "ComboString", "JLabel",
                "JComboBox" },
            { new Boolean(true), "Boolean", "JCheckBox",
                "JCheckBox" },
            { new Boolean(false), "Boolean", "JCheckBox",
                "JCheckBox" },
            { "true", "String", "JLabel", "JTextField" },
            { "false", "String", "JLabel", "JTextField" } },
        new Object[] { "Component", "Data", "Renderer", "Editor" });
    JTable table = new JTable(dm);
    table.getColumn("Component").setCellRenderer(new MultiRenderer());
    table.getColumn("Component").setCellEditor(new MultiEditor());
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll);
    setSize(400, 160);
    setVisible(true);
  }
  public static void main(String[] args) {
    MultiComponentTable frame = new MultiComponentTable();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}





multiple Font Cell Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
/**
 * @version 1.0 11/22/98
 */
public class MultiFontCellTableExample extends JFrame {
  public MultiFontCellTableExample() {
    super("Multi-Font Cell Example");
    AttributiveCellTableModel ml = new AttributiveCellTableModel(8, 3);
    CellFont cellAtt = (CellFont) ml.getCellAttribute();
    JTable table = new JTable(ml);
    table.setRowHeight(26);
    table.setCellSelectionEnabled(true);
    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    table.setDefaultRenderer(Object.class, new AttributiveCellRenderer());
    JScrollPane scroll = new JScrollPane(table);
    FontPanel fontPanel = new FontPanel(table, cellAtt);
    Box box = new Box(BoxLayout.X_AXIS);
    box.add(scroll);
    box.add(new JSeparator(SwingConstants.HORIZONTAL));
    box.add(fontPanel);
    getContentPane().add(box);
    setSize(400, 200);
    setVisible(true);
  }
  class FontPanel extends JPanel {
    String[] str_size = { "10", "12", "14", "16", "20", "24" };
    String[] str_style = { "PLAIN", "BOLD", "ITALIC" };
    JComboBox name, style, size;
    FontPanel(final JTable table, final CellFont cellAtt) {
      setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
      Box box = new Box(BoxLayout.X_AXIS);
      JPanel p2 = new JPanel(new GridLayout(3, 1));
      JPanel p3 = new JPanel(new GridLayout(3, 1));
      JPanel p4 = new JPanel(new FlowLayout());
      p2.add(new JLabel("Name:"));
      p2.add(new JLabel("Style:"));
      p2.add(new JLabel("Size:"));
      Toolkit toolkit = Toolkit.getDefaultToolkit();
      name = new JComboBox(toolkit.getFontList());
      style = new JComboBox(str_style);
      size = new JComboBox(str_size);
      size.setEditable(true);
      JButton b_apply = new JButton("Apply");
      b_apply.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          int[] columns = table.getSelectedColumns();
          int[] rows = table.getSelectedRows();
          if ((rows == null) || (columns == null))
            return;
          if ((rows.length < 1) || (columns.length < 1))
            return;
          Font font = new Font((String) name.getSelectedItem(), style
              .getSelectedIndex(), Integer.parseInt((String) size
              .getSelectedItem()));
          cellAtt.setFont(font, rows, columns);
          table.clearSelection();
          table.revalidate();
          table.repaint();
        }
      });
      p3.add(name);
      p3.add(style);
      p3.add(size);
      p4.add(b_apply);
      box.add(p2);
      box.add(p3);
      add(box);
      add(p4);
    }
  }
  public static void main(String[] args) {
    MultiFontCellTableExample frame = new MultiFontCellTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
/**
 * @version 1.0 11/22/98
 */
class AttributiveCellTableModel extends DefaultTableModel {
  protected CellAttribute cellAtt;
  public AttributiveCellTableModel() {
    this((Vector) null, 0);
  }
  public AttributiveCellTableModel(int numRows, int numColumns) {
    Vector names = new Vector(numColumns);
    names.setSize(numColumns);
    setColumnIdentifiers(names);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows, numColumns);
  }
  public AttributiveCellTableModel(Vector columnNames, int numRows) {
    setColumnIdentifiers(columnNames);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
  }
  public AttributiveCellTableModel(Object[] columnNames, int numRows) {
    this(convertToVector(columnNames), numRows);
  }
  public AttributiveCellTableModel(Vector data, Vector columnNames) {
    setDataVector(data, columnNames);
  }
  public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
    setDataVector(data, columnNames);
  }
  public void setDataVector(Vector newData, Vector columnNames) {
    if (newData == null)
      throw new IllegalArgumentException(
          "setDataVector() - Null parameter");
    dataVector = new Vector(0);
    setColumnIdentifiers(columnNames);
    dataVector = newData;
    //
    cellAtt = new DefaultCellAttribute(dataVector.size(), columnIdentifiers
        .size());
    newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public void addColumn(Object columnName, Vector columnData) {
    if (columnName == null)
      throw new IllegalArgumentException("addColumn() - null parameter");
    columnIdentifiers.addElement(columnName);
    int index = 0;
    Enumeration eeration = dataVector.elements();
    while (eeration.hasMoreElements()) {
      Object value;
      if ((columnData != null) && (index < columnData.size()))
        value = columnData.elementAt(index);
      else
        value = null;
      ((Vector) eeration.nextElement()).addElement(value);
      index++;
    }
    //
    cellAtt.addColumn();
    fireTableStructureChanged();
  }
  public void addRow(Vector rowData) {
    Vector newData = null;
    if (rowData == null) {
      newData = new Vector(getColumnCount());
    } else {
      rowData.setSize(getColumnCount());
    }
    dataVector.addElement(newData);
    //
    cellAtt.addRow();
    newRowsAdded(new TableModelEvent(this, getRowCount() - 1,
        getRowCount() - 1, TableModelEvent.ALL_COLUMNS,
        TableModelEvent.INSERT));
  }
  public void insertRow(int row, Vector rowData) {
    if (rowData == null) {
      rowData = new Vector(getColumnCount());
    } else {
      rowData.setSize(getColumnCount());
    }
    dataVector.insertElementAt(rowData, row);
    //
    cellAtt.insertRow(row);
    newRowsAdded(new TableModelEvent(this, row, row,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public CellAttribute getCellAttribute() {
    return cellAtt;
  }
  public void setCellAttribute(CellAttribute newCellAtt) {
    int numColumns = getColumnCount();
    int numRows = getRowCount();
    if ((newCellAtt.getSize().width != numColumns)
        || (newCellAtt.getSize().height != numRows)) {
      newCellAtt.setSize(new Dimension(numRows, numColumns));
    }
    cellAtt = newCellAtt;
    fireTableDataChanged();
  }
  /*
   * public void changeCellAttribute(int row, int column, Object command) {
   * cellAtt.changeAttribute(row, column, command); }
   * 
   * public void changeCellAttribute(int[] rows, int[] columns, Object
   * command) { cellAtt.changeAttribute(rows, columns, command); }
   */
}
/**
 * @version 1.0 11/22/98
 */
class DefaultCellAttribute
//    implements CellAttribute ,CellSpan {
    implements CellAttribute, CellSpan, ColoredCell, CellFont {
  //
  // !!!! CAUTION !!!!!
  // these values must be synchronized to Table data
  //
  protected int rowSize;
  protected int columnSize;
  protected int[][][] span; // CellSpan
  protected Color[][] foreground; // ColoredCell
  protected Color[][] background; //
  protected Font[][] font; // CellFont
  public DefaultCellAttribute() {
    this(1, 1);
  }
  public DefaultCellAttribute(int numRows, int numColumns) {
    setSize(new Dimension(numColumns, numRows));
  }
  protected void initValue() {
    for (int i = 0; i < span.length; i++) {
      for (int j = 0; j < span[i].length; j++) {
        span[i][j][CellSpan.COLUMN] = 1;
        span[i][j][CellSpan.ROW] = 1;
      }
    }
  }
  //
  // CellSpan
  //
  public int[] getSpan(int row, int column) {
    if (isOutOfBounds(row, column)) {
      int[] ret_code = { 1, 1 };
      return ret_code;
    }
    return span[row][column];
  }
  public void setSpan(int[] span, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    this.span[row][column] = span;
  }
  public boolean isVisible(int row, int column) {
    if (isOutOfBounds(row, column))
      return false;
    if ((span[row][column][CellSpan.COLUMN] < 1)
        || (span[row][column][CellSpan.ROW] < 1))
      return false;
    return true;
  }
  public void combine(int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    int rowSpan = rows.length;
    int columnSpan = columns.length;
    int startRow = rows[0];
    int startColumn = columns[0];
    for (int i = 0; i < rowSpan; i++) {
      for (int j = 0; j < columnSpan; j++) {
        if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
            || (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
          //System.out.println("can"t combine");
          return;
        }
      }
    }
    for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
      for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
        span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
        span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
        //System.out.println("r " +ii +" c " +jj);
      }
    }
    span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
    span[startRow][startColumn][CellSpan.ROW] = rowSpan;
  }
  public void split(int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    int columnSpan = span[row][column][CellSpan.COLUMN];
    int rowSpan = span[row][column][CellSpan.ROW];
    for (int i = 0; i < rowSpan; i++) {
      for (int j = 0; j < columnSpan; j++) {
        span[row + i][column + j][CellSpan.COLUMN] = 1;
        span[row + i][column + j][CellSpan.ROW] = 1;
      }
    }
  }
  //
  // ColoredCell
  //
  public Color getForeground(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return foreground[row][column];
  }
  public void setForeground(Color color, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    foreground[row][column] = color;
  }
  public void setForeground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(foreground, color, rows, columns);
  }
  public Color getBackground(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return background[row][column];
  }
  public void setBackground(Color color, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    background[row][column] = color;
  }
  public void setBackground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(background, color, rows, columns);
  }
  //
  //
  // CellFont
  //
  public Font getFont(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return font[row][column];
  }
  public void setFont(Font font, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    this.font[row][column] = font;
  }
  public void setFont(Font font, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(this.font, font, rows, columns);
  }
  //
  //
  // CellAttribute
  //
  public void addColumn() {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows][numColumns + 1][2];
    System.arraycopy(oldSpan, 0, span, 0, numRows);
    for (int i = 0; i < numRows; i++) {
      span[i][numColumns][CellSpan.COLUMN] = 1;
      span[i][numColumns][CellSpan.ROW] = 1;
    }
  }
  public void addRow() {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    System.arraycopy(oldSpan, 0, span, 0, numRows);
    for (int i = 0; i < numColumns; i++) {
      span[numRows][i][CellSpan.COLUMN] = 1;
      span[numRows][i][CellSpan.ROW] = 1;
    }
  }
  public void insertRow(int row) {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    if (0 < row) {
      System.arraycopy(oldSpan, 0, span, 0, row - 1);
    }
    System.arraycopy(oldSpan, 0, span, row, numRows - row);
    for (int i = 0; i < numColumns; i++) {
      span[row][i][CellSpan.COLUMN] = 1;
      span[row][i][CellSpan.ROW] = 1;
    }
  }
  public Dimension getSize() {
    return new Dimension(rowSize, columnSize);
  }
  public void setSize(Dimension size) {
    columnSize = size.width;
    rowSize = size.height;
    span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
    foreground = new Color[rowSize][columnSize];
    background = new Color[rowSize][columnSize];
    font = new Font[rowSize][columnSize];
    initValue();
  }
  /*
   * public void changeAttribute(int row, int column, Object command) { }
   * 
   * public void changeAttribute(int[] rows, int[] columns, Object command) { }
   */
  protected boolean isOutOfBounds(int row, int column) {
    if ((row < 0) || (rowSize <= row) || (column < 0)
        || (columnSize <= column)) {
      return true;
    }
    return false;
  }
  protected boolean isOutOfBounds(int[] rows, int[] columns) {
    for (int i = 0; i < rows.length; i++) {
      if ((rows[i] < 0) || (rowSize <= rows[i]))
        return true;
    }
    for (int i = 0; i < columns.length; i++) {
      if ((columns[i] < 0) || (columnSize <= columns[i]))
        return true;
    }
    return false;
  }
  protected void setValues(Object[][] target, Object value, int[] rows,
      int[] columns) {
    for (int i = 0; i < rows.length; i++) {
      int row = rows[i];
      for (int j = 0; j < columns.length; j++) {
        int column = columns[j];
        target[row][column] = value;
      }
    }
  }
}
/**
 * @version 1.0 11/22/98
 */
/*
 * (swing1.1beta3)
 *  
 */
/**
 * @version 1.0 11/22/98
 */
interface CellAttribute {
  public void addColumn();
  public void addRow();
  public void insertRow(int row);
  public Dimension getSize();
  public void setSize(Dimension size);
}
interface ColoredCell {
  public Color getForeground(int row, int column);
  public void setForeground(Color color, int row, int column);
  public void setForeground(Color color, int[] rows, int[] columns);
  public Color getBackground(int row, int column);
  public void setBackground(Color color, int row, int column);
  public void setBackground(Color color, int[] rows, int[] columns);
}
/**
 * @version 1.0 11/22/98
 */
class AttributiveCellRenderer extends JLabel implements TableCellRenderer {
  protected static Border noFocusBorder;
  public AttributiveCellRenderer() {
    noFocusBorder = new EmptyBorder(1, 2, 1, 2);
    setOpaque(true);
    setBorder(noFocusBorder);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    Color foreground = null;
    Color background = null;
    Font font = null;
    TableModel model = table.getModel();
    if (model instanceof AttributiveCellTableModel) {
      CellAttribute cellAtt = ((AttributiveCellTableModel) model)
          .getCellAttribute();
      if (cellAtt instanceof ColoredCell) {
        foreground = ((ColoredCell) cellAtt).getForeground(row, column);
        background = ((ColoredCell) cellAtt).getBackground(row, column);
      }
      if (cellAtt instanceof CellFont) {
        font = ((CellFont) cellAtt).getFont(row, column);
      }
    }
    if (isSelected) {
      setForeground((foreground != null) ? foreground : table
          .getSelectionForeground());
      setBackground(table.getSelectionBackground());
    } else {
      setForeground((foreground != null) ? foreground : table
          .getForeground());
      setBackground((background != null) ? background : table
          .getBackground());
    }
    setFont((font != null) ? font : table.getFont());
    if (hasFocus) {
      setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      if (table.isCellEditable(row, column)) {
        setForeground((foreground != null) ? foreground : UIManager
            .getColor("Table.focusCellForeground"));
        setBackground(UIManager.getColor("Table.focusCellBackground"));
      }
    } else {
      setBorder(noFocusBorder);
    }
    setValue(value);
    return this;
  }
  protected void setValue(Object value) {
    setText((value == null) ? "" : value.toString());
  }
}
/**
 * @version 1.0 11/22/98
 */
class TextPreviewLabel extends JLabel {
  private String sampleText = "  Sample Text  Sample Text  ";
  boolean isForgroundSelection;
  public TextPreviewLabel() {
    this(Color.black, Color.white, true);
  }
  public TextPreviewLabel(Color fore, Color back, boolean isForgroundSelection) {
    setOpaque(true);
    setForeground(fore);
    setBackground(back);
    this.isForgroundSelection = isForgroundSelection;
    setText(sampleText);
  }
  public void setForeground(Color col) {
    if (isForgroundSelection) {
      super.setForeground(col);
    } else {
      super.setBackground(col);
    }
  }
}
class ColorChooserDialog extends JDialog {
  private Color initialColor;
  private Color retColor;
  private JColorChooser chooserPane;
  public ColorChooserDialog(Component c, String title,
      final JColorChooser chooserPane) {
    super(JOptionPane.getFrameForComponent(c), title, true);
    setResizable(false);
    this.chooserPane = chooserPane;
    String okString = UIManager.getString("ColorChooser.okText");
    String cancelString = UIManager.getString("ColorChooser.cancelText");
    String resetString = UIManager.getString("ColorChooser.resetText");
    Container contentPane = getContentPane();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(chooserPane, BorderLayout.CENTER);
    JPanel buttonPane = new JPanel();
    buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
    JButton okButton = new JButton(okString);
    getRootPane().setDefaultButton(okButton);
    okButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        retColor = chooserPane.getColor();
        setVisible(false);
      }
    });
    buttonPane.add(okButton);
    JButton cancelButton = new JButton(cancelString);
    cancelButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        retColor = null;
        setVisible(false);
      }
    });
    buttonPane.add(cancelButton);
    JButton resetButton = new JButton(resetString);
    resetButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        chooserPane.setColor(initialColor);
      }
    });
    buttonPane.add(resetButton);
    contentPane.add(buttonPane, BorderLayout.SOUTH);
    pack();
    setLocationRelativeTo(c);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        setVisible(false);
      }
    });
  }
  public Color getColor() {
    return retColor;
  }
}
class TextColorChooser extends JColorChooser {
  public TextColorChooser(Color target, Color reference,
      boolean isForgroundSelection) {
    super(target);
    if (isForgroundSelection) {
      setPreviewPanel(new TextPreviewLabel(target, reference,
          isForgroundSelection));
    } else {
      setPreviewPanel(new TextPreviewLabel(reference, target,
          isForgroundSelection));
    }
    updateUI();
  }
  public Color showDialog(Component component, String title) {
    ColorChooserDialog dialog = new ColorChooserDialog(component, title,
        this);
    dialog.show();
    Color col = dialog.getColor();
    dialog.dispose();
    return col;
  }
}
interface CellFont {
  public Font getFont(int row, int column);
  public void setFont(Font font, int row, int column);
  public void setFont(Font font, int[] rows, int[] columns);
}
interface CellSpan {
  public final int ROW = 0;
  public final int COLUMN = 1;
  public int[] getSpan(int row, int column);
  public void setSpan(int[] span, int row, int column);
  public boolean isVisible(int row, int column);
  public void combine(int[] rows, int[] columns);
  public void split(int row, int column);
}





multiple Row Header Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) (swing#1356,#1454) */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
/*   ----------------------------------------------
 *  |         SNo.        |
 *   ----------------------------------------------
 *  |          |     1    |
 *  |   Name   |-----------------------------------
 *  |          |     2    |
 *   ----------------------------------------------
 *  |          |     1    |
 *  |          |-----------------------------------
 *  | Language |     2    |
 *  |          |-----------------------------------
 *  |          |     3    |
 *   ----------------------------------------------
 */
/**
 * @version 1.0 03/06/99
 */
public class MultipleRowHeaderExample extends JFrame {
  Object[][] data;
  Object[] column;
  JTable table;
  MultiSpanCellTable fixedTable;
  public MultipleRowHeaderExample() {
    super("Multiple Row Header Example");
    setSize(400, 150);
    data = new Object[][] { { "SNo.", "" }, { "Name", "1" }, { "", "2" },
        { "Language", "1" }, { "", "2" }, { "", "3" } };
    column = new Object[] { "", "" };
    AttributiveCellTableModel fixedModel = new AttributiveCellTableModel(
        data, column) {
      public boolean CellEditable(int row, int col) {
        return false;
      }
    };
    CellSpan cellAtt = (CellSpan) fixedModel.getCellAttribute();
    cellAtt.rubine(new int[] { 0 }, new int[] { 0, 1 });
    cellAtt.rubine(new int[] { 1, 2 }, new int[] { 0 });
    cellAtt.rubine(new int[] { 3, 4, 5 }, new int[] { 0 });
    DefaultTableModel model = new DefaultTableModel(data.length, 3);
    fixedTable = new MultiSpanCellTable(fixedModel);
    table = new JTable(model);
    fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    fixedTable.setDefaultRenderer(Object.class, new RowHeaderRenderer(
        fixedTable));
    fixedTable.setGridColor(table.getTableHeader().getBackground());
    JScrollPane scroll = new JScrollPane(table);
    JViewport viewport = new JViewport();
    viewport.setView(fixedTable);
    viewport.setPreferredSize(fixedTable.getPreferredSize());
    scroll.setRowHeaderView(viewport);
    getContentPane().add(scroll, BorderLayout.CENTER);
  }
  public static void main(String[] args) {
    MultipleRowHeaderExample frame = new MultipleRowHeaderExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setVisible(true);
  }
  class RowHeaderRenderer extends JLabel implements TableCellRenderer {
    RowHeaderRenderer(JTable table) {
      JTableHeader header = table.getTableHeader();
      setOpaque(true);
      setBorder(UIManager.getBorder("TableHeader.cellBorder"));
      setHorizontalAlignment(CENTER);
      setForeground(header.getForeground());
      setBackground(header.getBackground());
      setFont(header.getFont());
    }
    public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column) {
      setText((value == null) ? "" : value.toString());
      return this;
    }
  }
}
class AttributiveCellTableModel extends DefaultTableModel {
  protected CellAttribute cellAtt;
  public AttributiveCellTableModel() {
    this((Vector) null, 0);
  }
  public AttributiveCellTableModel(int numRows, int numColumns) {
    Vector names = new Vector(numColumns);
    names.setSize(numColumns);
    setColumnIdentifiers(names);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows, numColumns);
  }
  public AttributiveCellTableModel(Vector columnNames, int numRows) {
    setColumnIdentifiers(columnNames);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
  }
  public AttributiveCellTableModel(Object[] columnNames, int numRows) {
    this(convertToVector(columnNames), numRows);
  }
  public AttributiveCellTableModel(Vector data, Vector columnNames) {
    setDataVector(data, columnNames);
  }
  public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
    setDataVector(data, columnNames);
  }
  public void setDataVector(Vector newData, Vector columnNames) {
    if (newData == null)
      throw new IllegalArgumentException(
          "setDataVector() - Null parameter");
    dataVector = new Vector(0);
    setColumnIdentifiers(columnNames);
    dataVector = newData;
    //
    cellAtt = new DefaultCellAttribute(dataVector.size(), columnIdentifiers
        .size());
    newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public void addColumn(Object columnName, Vector columnData) {
    if (columnName == null)
      throw new IllegalArgumentException("addColumn() - null parameter");
    columnIdentifiers.addElement(columnName);
    int index = 0;
    Enumeration enumeration = dataVector.elements();
    while (enumeration.hasMoreElements()) {
      Object value;
      if ((columnData != null) && (index < columnData.size()))
        value = columnData.elementAt(index);
      else
        value = null;
      ((Vector) enumeration.nextElement()).addElement(value);
      index++;
    }
    //
    cellAtt.addColumn();
    fireTableStructureChanged();
  }
  public void addRow(Vector rowData) {
    Vector newData = null;
    if (rowData == null) {
      newData = new Vector(getColumnCount());
    } else {
      rowData.setSize(getColumnCount());
    }
    dataVector.addElement(newData);
    //
    cellAtt.addRow();
    newRowsAdded(new TableModelEvent(this, getRowCount() - 1,
        getRowCount() - 1, TableModelEvent.ALL_COLUMNS,
        TableModelEvent.INSERT));
  }
  public void insertRow(int row, Vector rowData) {
    if (rowData == null) {
      rowData = new Vector(getColumnCount());
    } else {
      rowData.setSize(getColumnCount());
    }
    dataVector.insertElementAt(rowData, row);
    //
    cellAtt.insertRow(row);
    newRowsAdded(new TableModelEvent(this, row, row,
        TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public CellAttribute getCellAttribute() {
    return cellAtt;
  }
  public void setCellAttribute(CellAttribute newCellAtt) {
    int numColumns = getColumnCount();
    int numRows = getRowCount();
    if ((newCellAtt.getSize().width != numColumns)
        || (newCellAtt.getSize().height != numRows)) {
      newCellAtt.setSize(new Dimension(numRows, numColumns));
    }
    cellAtt = newCellAtt;
    fireTableDataChanged();
  }
  /*
   * public void changeCellAttribute(int row, int column, Object command) {
   * cellAtt.changeAttribute(row, column, command); }
   * 
   * public void changeCellAttribute(int[] rows, int[] columns, Object
   * command) { cellAtt.changeAttribute(rows, columns, command); }
   */
}
class DefaultCellAttribute
//implements CellAttribute ,CellSpan {
    implements CellAttribute, CellSpan, ColoredCell, CellFont {
  //
  // !!!! CAUTION !!!!!
  // these values must be synchronized to Table data
  //
  protected int rowSize;
  protected int columnSize;
  protected int[][][] span; // CellSpan
  protected Color[][] foreground; // ColoredCell
  protected Color[][] background; //
  protected Font[][] font; // CellFont
  public DefaultCellAttribute() {
    this(1, 1);
  }
  public DefaultCellAttribute(int numRows, int numColumns) {
    setSize(new Dimension(numColumns, numRows));
  }
  protected void initValue() {
    for (int i = 0; i < span.length; i++) {
      for (int j = 0; j < span[i].length; j++) {
        span[i][j][CellSpan.COLUMN] = 1;
        span[i][j][CellSpan.ROW] = 1;
      }
    }
  }
  //
  // CellSpan
  //
  public int[] getSpan(int row, int column) {
    if (isOutOfBounds(row, column)) {
      int[] ret_code = { 1, 1 };
      return ret_code;
    }
    return span[row][column];
  }
  public void setSpan(int[] span, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    this.span[row][column] = span;
  }
  public boolean isVisible(int row, int column) {
    if (isOutOfBounds(row, column))
      return false;
    if ((span[row][column][CellSpan.COLUMN] < 1)
        || (span[row][column][CellSpan.ROW] < 1))
      return false;
    return true;
  }
  public void combine(int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    int rowSpan = rows.length;
    int columnSpan = columns.length;
    int startRow = rows[0];
    int startColumn = columns[0];
    for (int i = 0; i < rowSpan; i++) {
      for (int j = 0; j < columnSpan; j++) {
        if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
            || (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
          //System.out.println("can"t combine");
          return;
        }
      }
    }
    for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
      for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
        span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
        span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
        //System.out.println("r " +ii +" c " +jj);
      }
    }
    span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
    span[startRow][startColumn][CellSpan.ROW] = rowSpan;
  }
  public void split(int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    int columnSpan = span[row][column][CellSpan.COLUMN];
    int rowSpan = span[row][column][CellSpan.ROW];
    for (int i = 0; i < rowSpan; i++) {
      for (int j = 0; j < columnSpan; j++) {
        span[row + i][column + j][CellSpan.COLUMN] = 1;
        span[row + i][column + j][CellSpan.ROW] = 1;
      }
    }
  }
  //
  // ColoredCell
  //
  public Color getForeground(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return foreground[row][column];
  }
  public void setForeground(Color color, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    foreground[row][column] = color;
  }
  public void setForeground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(foreground, color, rows, columns);
  }
  public Color getBackground(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return background[row][column];
  }
  public void setBackground(Color color, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    background[row][column] = color;
  }
  public void setBackground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(background, color, rows, columns);
  }
  //
  //
  // CellFont
  //
  public Font getFont(int row, int column) {
    if (isOutOfBounds(row, column))
      return null;
    return font[row][column];
  }
  public void setFont(Font font, int row, int column) {
    if (isOutOfBounds(row, column))
      return;
    this.font[row][column] = font;
  }
  public void setFont(Font font, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns))
      return;
    setValues(this.font, font, rows, columns);
  }
  //
  //
  // CellAttribute
  //
  public void addColumn() {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows][numColumns + 1][2];
    System.arraycopy(oldSpan, 0, span, 0, numRows);
    for (int i = 0; i < numRows; i++) {
      span[i][numColumns][CellSpan.COLUMN] = 1;
      span[i][numColumns][CellSpan.ROW] = 1;
    }
  }
  public void addRow() {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    System.arraycopy(oldSpan, 0, span, 0, numRows);
    for (int i = 0; i < numColumns; i++) {
      span[numRows][i][CellSpan.COLUMN] = 1;
      span[numRows][i][CellSpan.ROW] = 1;
    }
  }
  public void insertRow(int row) {
    int[][][] oldSpan = span;
    int numRows = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    if (0 < row) {
      System.arraycopy(oldSpan, 0, span, 0, row - 1);
    }
    System.arraycopy(oldSpan, 0, span, row, numRows - row);
    for (int i = 0; i < numColumns; i++) {
      span[row][i][CellSpan.COLUMN] = 1;
      span[row][i][CellSpan.ROW] = 1;
    }
  }
  public Dimension getSize() {
    return new Dimension(rowSize, columnSize);
  }
  public void setSize(Dimension size) {
    columnSize = size.width;
    rowSize = size.height;
    span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
    foreground = new Color[rowSize][columnSize];
    background = new Color[rowSize][columnSize];
    font = new Font[rowSize][columnSize];
    initValue();
  }
  /*
   * public void changeAttribute(int row, int column, Object command) { }
   * 
   * public void changeAttribute(int[] rows, int[] columns, Object command) { }
   */
  protected boolean isOutOfBounds(int row, int column) {
    if ((row < 0) || (rowSize <= row) || (column < 0)
        || (columnSize <= column)) {
      return true;
    }
    return false;
  }
  protected boolean isOutOfBounds(int[] rows, int[] columns) {
    for (int i = 0; i < rows.length; i++) {
      if ((rows[i] < 0) || (rowSize <= rows[i]))
        return true;
    }
    for (int i = 0; i < columns.length; i++) {
      if ((columns[i] < 0) || (columnSize <= columns[i]))
        return true;
    }
    return false;
  }
  protected void setValues(Object[][] target, Object value, int[] rows,
      int[] columns) {
    for (int i = 0; i < rows.length; i++) {
      int row = rows[i];
      for (int j = 0; j < columns.length; j++) {
        int column = columns[j];
        target[row][column] = value;
      }
    }
  }
}
interface CellAttribute {
  public void addColumn();
  public void addRow();
  public void insertRow(int row);
  public Dimension getSize();
  public void setSize(Dimension size);
}
interface ColoredCell {
  public Color getForeground(int row, int column);
  public void setForeground(Color color, int row, int column);
  public void setForeground(Color color, int[] rows, int[] columns);
  public Color getBackground(int row, int column);
  public void setBackground(Color color, int row, int column);
  public void setBackground(Color color, int[] rows, int[] columns);
}
interface CellFont {
  public Font getFont(int row, int column);
  public void setFont(Font font, int row, int column);
  public void setFont(Font font, int[] rows, int[] columns);
}
interface CellSpan {
  public final int ROW = 0;
  public final int COLUMN = 1;
  public int[] getSpan(int row, int column);
  public void setSpan(int[] span, int row, int column);
  public boolean isVisible(int row, int column);
  public void combine(int[] rows, int[] columns);
  public void split(int row, int column);
}
class MultiSpanCellTable extends JTable {
  public MultiSpanCellTable(TableModel model) {
    super(model);
    setUI(new MultiSpanCellTableUI());
    getTableHeader().setReorderingAllowed(false);
    setCellSelectionEnabled(true);
    setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
  }
  public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
    Rectangle sRect = super.getCellRect(row, column, includeSpacing);
    if ((row < 0) || (column < 0) || (getRowCount() <= row)
        || (getColumnCount() <= column)) {
      return sRect;
    }
    CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel())
        .getCellAttribute();
    if (!cellAtt.isVisible(row, column)) {
      int temp_row = row;
      int temp_column = column;
      row += cellAtt.getSpan(temp_row, temp_column)[CellSpan.ROW];
      column += cellAtt.getSpan(temp_row, temp_column)[CellSpan.COLUMN];
    }
    int[] n = cellAtt.getSpan(row, column);
    int index = 0;
    int columnMargin = getColumnModel().getColumnMargin();
    Rectangle cellFrame = new Rectangle();
    int aCellHeight = rowHeight + rowMargin;
    cellFrame.y = row * aCellHeight;
    cellFrame.height = n[CellSpan.ROW] * aCellHeight;
    Enumeration enumeration = getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
      TableColumn aColumn = (TableColumn) enumeration.nextElement();
      cellFrame.width = aColumn.getWidth() + columnMargin;
      if (index == column)
        break;
      cellFrame.x += cellFrame.width;
      index++;
    }
    for (int i = 0; i < n[CellSpan.COLUMN] - 1; i++) {
      TableColumn aColumn = (TableColumn) enumeration.nextElement();
      cellFrame.width += aColumn.getWidth() + columnMargin;
    }
    if (!includeSpacing) {
      Dimension spacing = getIntercellSpacing();
      cellFrame.setBounds(cellFrame.x + spacing.width / 2, cellFrame.y
          + spacing.height / 2, cellFrame.width - spacing.width,
          cellFrame.height - spacing.height);
    }
    return cellFrame;
  }
  private int[] rowColumnAtPoint(Point point) {
    int[] retValue = { -1, -1 };
    int row = point.y / (rowHeight + rowMargin);
    if ((row < 0) || (getRowCount() <= row))
      return retValue;
    int column = getColumnModel().getColumnIndexAtX(point.x);
    CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel())
        .getCellAttribute();
    if (cellAtt.isVisible(row, column)) {
      retValue[CellSpan.COLUMN] = column;
      retValue[CellSpan.ROW] = row;
      return retValue;
    }
    retValue[CellSpan.COLUMN] = column
        + cellAtt.getSpan(row, column)[CellSpan.COLUMN];
    retValue[CellSpan.ROW] = row
        + cellAtt.getSpan(row, column)[CellSpan.ROW];
    return retValue;
  }
  public int rowAtPoint(Point point) {
    return rowColumnAtPoint(point)[CellSpan.ROW];
  }
  public int columnAtPoint(Point point) {
    return rowColumnAtPoint(point)[CellSpan.COLUMN];
  }
  public void columnSelectionChanged(ListSelectionEvent e) {
    repaint();
  }
  public void valueChanged(ListSelectionEvent e) {
    int firstIndex = e.getFirstIndex();
    int lastIndex = e.getLastIndex();
    if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
      repaint();
    }
    Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
    int numCoumns = getColumnCount();
    int index = firstIndex;
    for (int i = 0; i < numCoumns; i++) {
      dirtyRegion.add(getCellRect(index, i, false));
    }
    index = lastIndex;
    for (int i = 0; i < numCoumns; i++) {
      dirtyRegion.add(getCellRect(index, i, false));
    }
    repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width,
        dirtyRegion.height);
  }
}
class MultiSpanCellTableUI extends BasicTableUI {
  public void paint(Graphics g, JComponent c) {
    Rectangle oldClipBounds = g.getClipBounds();
    Rectangle clipBounds = new Rectangle(oldClipBounds);
    int tableWidth = table.getColumnModel().getTotalColumnWidth();
    clipBounds.width = Math.min(clipBounds.width, tableWidth);
    g.setClip(clipBounds);
    int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y));
    int lastIndex = table.getRowCount() - 1;
    Rectangle rowRect = new Rectangle(0, 0, tableWidth, table
        .getRowHeight()
        + table.getRowMargin());
    rowRect.y = firstIndex * rowRect.height;
    for (int index = firstIndex; index <= lastIndex; index++) {
      if (rowRect.intersects(clipBounds)) {
        //System.out.println(); // debug
        //System.out.print("" + index +": "); // row
        paintRow(g, index);
      }
      rowRect.y += rowRect.height;
    }
    g.setClip(oldClipBounds);
  }
  private void paintRow(Graphics g, int row) {
    Rectangle rect = g.getClipBounds();
    boolean drawn = false;
    AttributiveCellTableModel tableModel = (AttributiveCellTableModel) table
        .getModel();
    CellSpan cellAtt = (CellSpan) tableModel.getCellAttribute();
    int numColumns = table.getColumnCount();
    for (int column = 0; column < numColumns; column++) {
      Rectangle cellRect = table.getCellRect(row, column, true);
      int cellRow, cellColumn;
      if (cellAtt.isVisible(row, column)) {
        cellRow = row;
        cellColumn = column;
        //  System.out.print(" "+column+" "); // debug
      } else {
        cellRow = row + cellAtt.getSpan(row, column)[CellSpan.ROW];
        cellColumn = column
            + cellAtt.getSpan(row, column)[CellSpan.COLUMN];
        //  System.out.print(" ("+column+")"); // debug
      }
      if (cellRect.intersects(rect)) {
        drawn = true;
        paintCell(g, cellRect, cellRow, cellColumn);
      } else {
        if (drawn)
          break;
      }
    }
  }
  private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
    int spacingHeight = table.getRowMargin();
    int spacingWidth = table.getColumnModel().getColumnMargin();
    Color c = g.getColor();
    g.setColor(table.getGridColor());
    g.drawRect(cellRect.x, cellRect.y, cellRect.width - 1,
        cellRect.height - 1);
    g.setColor(c);
    cellRect.setBounds(cellRect.x + spacingWidth / 2, cellRect.y
        + spacingHeight / 2, cellRect.width - spacingWidth,
        cellRect.height - spacingHeight);
    if (table.isEditing() && table.getEditingRow() == row
        && table.getEditingColumn() == column) {
      Component component = table.getEditorComponent();
      component.setBounds(cellRect);
      component.validate();
    } else {
      TableCellRenderer renderer = table.getCellRenderer(row, column);
      Component component = table.prepareRenderer(renderer, row, column);
      if (component.getParent() == null) {
        rendererPane.add(component);
      }
      rendererPane.paintComponent(g, component, table, cellRect.x,
          cellRect.y, cellRect.width, cellRect.height, true);
    }
  }
}





Multi Span Cell Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

/**
 * @version 1.0 11/26/98
 */
public class MultiSpanCellTableExample extends JFrame {
  MultiSpanCellTableExample() {
    super( "Multi-Span Cell Example" );
    
    AttributiveCellTableModel ml = new AttributiveCellTableModel(10,6);
    /*
    AttributiveCellTableModel ml = new AttributiveCellTableModel(10,6) {
      public Object getValueAt(int row, int col) { 
        return "" + row + ","+ col; 
      }
    };
    */
    final CellSpan cellAtt =(CellSpan)ml.getCellAttribute();
    final MultiSpanCellTable table = new MultiSpanCellTable( ml );
    JScrollPane scroll = new JScrollPane( table );
    JButton b_one   = new JButton("Combine");
    b_one.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
  int[] columns = table.getSelectedColumns();
  int[] rows    = table.getSelectedRows();
  cellAtt.rubine(rows,columns);
  table.clearSelection();
  table.revalidate();
  table.repaint();
      }
    });
    JButton b_split = new JButton("Split");
    b_split.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
  int column = table.getSelectedColumn();
  int row    = table.getSelectedRow();
  cellAtt.split(row,column);
  table.clearSelection();
  table.revalidate();
  table.repaint();
      }
    });
    JPanel p_buttons = new JPanel();
    p_buttons.setLayout(new GridLayout(2,1));
    p_buttons.add(b_one);
    p_buttons.add(b_split);
    Box box = new Box(BoxLayout.X_AXIS);
    box.add(scroll);
    box.add(new JSeparator(SwingConstants.HORIZONTAL));
    box.add(p_buttons);
    getContentPane().add( box );
    setSize( 400, 200 );
    setVisible(true);
  }
  public static void main(String[] args) {
    MultiSpanCellTableExample frame = new MultiSpanCellTableExample();
    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing( WindowEvent e ) {
        System.exit(0);
      }
    });
  }
}

/**
 * @version 1.0 11/22/98
 */
class AttributiveCellTableModel extends DefaultTableModel {
  protected CellAttribute cellAtt;
    
  public AttributiveCellTableModel() {
    this((Vector)null, 0);
  }
  public AttributiveCellTableModel(int numRows, int numColumns) {
    Vector names = new Vector(numColumns);
    names.setSize(numColumns);
    setColumnIdentifiers(names);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows,numColumns);
  }
  public AttributiveCellTableModel(Vector columnNames, int numRows) {
    setColumnIdentifiers(columnNames);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows,columnNames.size());
  }
  public AttributiveCellTableModel(Object[] columnNames, int numRows) {
    this(convertToVector(columnNames), numRows);
  }  
  public AttributiveCellTableModel(Vector data, Vector columnNames) {
    setDataVector(data, columnNames);
  }
  public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
    setDataVector(data, columnNames);
  }
    
  public void setDataVector(Vector newData, Vector columnNames) {
    if (newData == null)
      throw new IllegalArgumentException("setDataVector() - Null parameter");
    dataVector = new Vector(0);
    setColumnIdentifiers(columnNames);
    dataVector = newData;
    
    //
    cellAtt = new DefaultCellAttribute(dataVector.size(),
                                       columnIdentifiers.size());
    
    newRowsAdded(new TableModelEvent(this, 0, getRowCount()-1,
     TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public void addColumn(Object columnName, Vector columnData) {
    if (columnName == null)
      throw new IllegalArgumentException("addColumn() - null parameter");
    columnIdentifiers.addElement(columnName);
    int index = 0;
    Enumeration eeration = dataVector.elements();
    while (eeration.hasMoreElements()) {
      Object value;
      if ((columnData != null) && (index < columnData.size()))
    value = columnData.elementAt(index);
      else
  value = null;
      ((Vector)eeration.nextElement()).addElement(value);
      index++;
    }
    //
    cellAtt.addColumn();
    fireTableStructureChanged();
  }
  public void addRow(Vector rowData) {
    Vector newData = null;
    if (rowData == null) {
      newData = new Vector(getColumnCount());
    }
    else {
      rowData.setSize(getColumnCount());
    }
    dataVector.addElement(newData);
    //
    cellAtt.addRow();
    newRowsAdded(new TableModelEvent(this, getRowCount()-1, getRowCount()-1,
       TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public void insertRow(int row, Vector rowData) {
    if (rowData == null) {
      rowData = new Vector(getColumnCount());
    }
    else {
      rowData.setSize(getColumnCount());
    }
    dataVector.insertElementAt(rowData, row);
    //
    cellAtt.insertRow(row);
    newRowsAdded(new TableModelEvent(this, row, row,
       TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  public CellAttribute getCellAttribute() {
    return cellAtt;
  }
  public void setCellAttribute(CellAttribute newCellAtt) {
    int numColumns = getColumnCount();
    int numRows    = getRowCount();
    if ((newCellAtt.getSize().width  != numColumns) ||
        (newCellAtt.getSize().height != numRows)) {
      newCellAtt.setSize(new Dimension(numRows, numColumns));
    }
    cellAtt = newCellAtt;
    fireTableDataChanged();
  }
  /*
  public void changeCellAttribute(int row, int column, Object command) {
    cellAtt.changeAttribute(row, column, command);
  }
  public void changeCellAttribute(int[] rows, int[] columns, Object command) {
    cellAtt.changeAttribute(rows, columns, command);
  }
  */
    
}

/**
 * @version 1.0 11/22/98
 */
class DefaultCellAttribute 
//    implements CellAttribute ,CellSpan  {
      implements CellAttribute ,CellSpan ,ColoredCell ,CellFont {
  //
  // !!!! CAUTION !!!!!
  // these values must be synchronized to Table data
  //
  protected int rowSize;
  protected int columnSize;
  protected int[][][] span;                   // CellSpan
  protected Color[][] foreground;             // ColoredCell
  protected Color[][] background;             //
  protected Font[][]  font;                   // CellFont
  
  public DefaultCellAttribute() {
    this(1,1);
  }
  
  public DefaultCellAttribute(int numRows, int numColumns) {
    setSize(new Dimension(numColumns, numRows));
  }
  protected void initValue() {
    for(int i=0; i<span.length;i++) {
      for(int j=0; j<span[i].length; j++) {
  span[i][j][CellSpan.COLUMN] = 1;
  span[i][j][CellSpan.ROW]    = 1;
      }
    }
  }

  //
  // CellSpan
  //
  public int[] getSpan(int row, int column) {
    if (isOutOfBounds(row, column)) {
      int[] ret_code = {1,1};
      return ret_code;
    }
    return span[row][column];
  }
  public void setSpan(int[] span, int row, int column) {
    if (isOutOfBounds(row, column)) return;
    this.span[row][column] = span;
  }
      
  public boolean isVisible(int row, int column) {
    if (isOutOfBounds(row, column)) return false;
    if ((span[row][column][CellSpan.COLUMN] < 1)
      ||(span[row][column][CellSpan.ROW]    < 1)) return false;
    return true;
  }
  public void combine(int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns)) return;
    int    rowSpan  = rows.length;
    int columnSpan  = columns.length;
    int startRow    = rows[0];
    int startColumn = columns[0];
    for (int i=0;i<rowSpan;i++) {
      for (int j=0;j<columnSpan;j++) {
  if ((span[startRow +i][startColumn +j][CellSpan.COLUMN] != 1)
    ||(span[startRow +i][startColumn +j][CellSpan.ROW]    != 1)) {
    //System.out.println("can"t combine");
    return ;
  }
      }
    }
    for (int i=0,ii=0;i<rowSpan;i++,ii--) {
      for (int j=0,jj=0;j<columnSpan;j++,jj--) {
  span[startRow +i][startColumn +j][CellSpan.COLUMN] = jj;
  span[startRow +i][startColumn +j][CellSpan.ROW]    = ii;
  //System.out.println("r " +ii +"  c " +jj);
      }
    }
    span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
    span[startRow][startColumn][CellSpan.ROW]    =    rowSpan;
    
  }
  public void split(int row, int column) {
    if (isOutOfBounds(row, column)) return;
    int columnSpan = span[row][column][CellSpan.COLUMN];
    int    rowSpan = span[row][column][CellSpan.ROW];
    for (int i=0;i<rowSpan;i++) {
      for (int j=0;j<columnSpan;j++) {
  span[row +i][column +j][CellSpan.COLUMN] = 1;
  span[row +i][column +j][CellSpan.ROW]    = 1;
      }
    }
  }

  //
  // ColoredCell
  //
  public Color getForeground(int row, int column) {
    if (isOutOfBounds(row, column)) return null;
    return foreground[row][column];
  }
  public void setForeground(Color color, int row, int column) {
    if (isOutOfBounds(row, column)) return;
    foreground[row][column] = color;
  }
  public void setForeground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns)) return;
    setValues(foreground, color, rows, columns);
  }
  public Color getBackground(int row, int column) {
    if (isOutOfBounds(row, column)) return null;
    return background[row][column];
  }
  public void setBackground(Color color, int row, int column) {
    if (isOutOfBounds(row, column)) return;
    background[row][column] = color;
  }
  public void setBackground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns)) return;
    setValues(background, color, rows, columns);
  }
  //

  //
  // CellFont
  //
  public Font getFont(int row, int column) {
    if (isOutOfBounds(row, column)) return null;
    return font[row][column];
  }
  public void setFont(Font font, int row, int column) {
    if (isOutOfBounds(row, column)) return;
    this.font[row][column] = font;
  }
  public void setFont(Font font, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns)) return;
    setValues(this.font, font, rows, columns);
  }
  //

  //
  // CellAttribute
  //
  public void addColumn() {
    int[][][] oldSpan = span;
    int numRows    = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows][numColumns + 1][2];
    System.arraycopy(oldSpan,0,span,0,numRows);
    for (int i=0;i<numRows;i++) {
      span[i][numColumns][CellSpan.COLUMN] = 1;
      span[i][numColumns][CellSpan.ROW]    = 1;
    }
  }
  public void addRow() {
    int[][][] oldSpan = span;
    int numRows    = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    System.arraycopy(oldSpan,0,span,0,numRows);
    for (int i=0;i<numColumns;i++) {
      span[numRows][i][CellSpan.COLUMN] = 1;
      span[numRows][i][CellSpan.ROW]    = 1;
    }
  }
  public void insertRow(int row) {
    int[][][] oldSpan = span;
    int numRows    = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    if (0 < row) {
      System.arraycopy(oldSpan,0,span,0,row-1);
    }
    System.arraycopy(oldSpan,0,span,row,numRows - row);
    for (int i=0;i<numColumns;i++) {
      span[row][i][CellSpan.COLUMN] = 1;
      span[row][i][CellSpan.ROW]    = 1;
    }
  }
  public Dimension getSize() {
    return new Dimension(rowSize, columnSize);
  }
  public void setSize(Dimension size) {
    columnSize = size.width;
    rowSize    = size.height;
    span = new int[rowSize][columnSize][2];   // 2: COLUMN,ROW
    foreground = new Color[rowSize][columnSize];
    background = new Color[rowSize][columnSize];
    font = new Font[rowSize][columnSize];
    initValue();
  }
  /*
  public void changeAttribute(int row, int column, Object command) {
  }
  public void changeAttribute(int[] rows, int[] columns, Object command) {
  }
  */


  protected boolean isOutOfBounds(int row, int column) {
    if ((row    < 0)||(rowSize    <= row)
      ||(column < 0)||(columnSize <= column)) {
      return true;
    }
    return false;
  }
  protected boolean isOutOfBounds(int[] rows, int[] columns) {
    for (int i=0;i<rows.length;i++) {
      if ((rows[i] < 0)||(rowSize <= rows[i])) return true;
    }
    for (int i=0;i<columns.length;i++) {
      if ((columns[i] < 0)||(columnSize <= columns[i])) return true;
    }
    return false;
  }
  protected void setValues(Object[][] target, Object value,
                           int[] rows, int[] columns) {
    for (int i=0;i<rows.length;i++) {
      int row = rows[i];
      for (int j=0;j<columns.length;j++) {
  int column = columns[j];
  target[row][column] = value;
      }
    }
  }
}
/*
 * (swing1.1beta3)
 * 
 */
/**
 * @version 1.0 11/22/98
 */
interface CellAttribute {
  public void addColumn();
  public void addRow();
  public void insertRow(int row);
  public Dimension getSize();
  public void setSize(Dimension size);

}
/*
 * (swing1.1beta3)
 * 
 */
/**
 * @version 1.0 11/22/98
 */
interface CellSpan {
  public final int ROW    = 0;
  public final int COLUMN = 1;
  
  public int[] getSpan(int row, int column);
  public void setSpan(int[] span, int row, int column);
  
  public boolean isVisible(int row, int column);
  
  public void combine(int[] rows, int[] columns);
  public void split(int row, int column);
}
/*
 * (swing1.1beta3)
 * 
 */
/**
 * @version 1.0 11/26/98
 */
class MultiSpanCellTable extends JTable {
  public MultiSpanCellTable(TableModel model) {
    super(model);
    setUI(new MultiSpanCellTableUI());
    getTableHeader().setReorderingAllowed(false);
    setCellSelectionEnabled(true);
    setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
  }
  
  
  public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
    Rectangle sRect = super.getCellRect(row,column,includeSpacing);
    if ((row <0) || (column<0) ||
        (getRowCount() <= row) || (getColumnCount() <= column)) {
        return sRect;
    }
    CellSpan cellAtt = (CellSpan)((AttributiveCellTableModel)getModel()).getCellAttribute();
    if (! cellAtt.isVisible(row,column)) {
      int temp_row    = row;
      int temp_column = column;
      row    += cellAtt.getSpan(temp_row,temp_column)[CellSpan.ROW];
      column += cellAtt.getSpan(temp_row,temp_column)[CellSpan.COLUMN];      
    }
    int[] n = cellAtt.getSpan(row,column);
    int index = 0;
    int columnMargin = getColumnModel().getColumnMargin();
    Rectangle cellFrame = new Rectangle();
    int aCellHeight = rowHeight + rowMargin;
    cellFrame.y = row * aCellHeight;
    cellFrame.height = n[CellSpan.ROW] * aCellHeight;
    
    Enumeration eeration = getColumnModel().getColumns();
    while (eeration.hasMoreElements()) {
      TableColumn aColumn = (TableColumn)eeration.nextElement();
      cellFrame.width = aColumn.getWidth() + columnMargin;
      if (index == column) break;
      cellFrame.x += cellFrame.width;
      index++;
    }
    for (int i=0;i< n[CellSpan.COLUMN]-1;i++) {
      TableColumn aColumn = (TableColumn)eeration.nextElement();
      cellFrame.width += aColumn.getWidth() + columnMargin;
    }
    
    
    if (!includeSpacing) {
      Dimension spacing = getIntercellSpacing();
      cellFrame.setBounds(cellFrame.x +      spacing.width/2,
        cellFrame.y +      spacing.height/2,
        cellFrame.width -  spacing.width,
        cellFrame.height - spacing.height);
    }
    return cellFrame;
  }
  
  
  private int[] rowColumnAtPoint(Point point) {
    int[] retValue = {-1,-1};
    int row = point.y / (rowHeight + rowMargin);
    if ((row <0)||(getRowCount() <= row)) return retValue;
    int column = getColumnModel().getColumnIndexAtX(point.x);
    CellSpan cellAtt = (CellSpan)((AttributiveCellTableModel)getModel()).getCellAttribute();
    if (cellAtt.isVisible(row,column)) {
      retValue[CellSpan.COLUMN] = column;
      retValue[CellSpan.ROW   ] = row;
      return retValue;
    }
    retValue[CellSpan.COLUMN] = column + cellAtt.getSpan(row,column)[CellSpan.COLUMN];
    retValue[CellSpan.ROW   ] = row + cellAtt.getSpan(row,column)[CellSpan.ROW];
    return retValue;
  }
  
  public int rowAtPoint(Point point) {
    return rowColumnAtPoint(point)[CellSpan.ROW];
  }
  public int columnAtPoint(Point point) {
    return rowColumnAtPoint(point)[CellSpan.COLUMN];
  }
 
  
  public void columnSelectionChanged(ListSelectionEvent e) {
    repaint();
  }
  public void valueChanged(ListSelectionEvent e) {
    int firstIndex = e.getFirstIndex();
    int  lastIndex = e.getLastIndex();
    if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
      repaint();
    }
    Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
    int numCoumns = getColumnCount();
    int index = firstIndex;
    for (int i=0;i<numCoumns;i++) {
      dirtyRegion.add(getCellRect(index, i, false));
    }
    index = lastIndex;
    for (int i=0;i<numCoumns;i++) {
      dirtyRegion.add(getCellRect(index, i, false));
    }
    repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  }
 
}

/**
 * @version 1.0 11/26/98
 */
class MultiSpanCellTableUI extends BasicTableUI {
  public void paint(Graphics g, JComponent c) {
    Rectangle oldClipBounds = g.getClipBounds();
    Rectangle clipBounds    = new Rectangle(oldClipBounds);
    int tableWidth   = table.getColumnModel().getTotalColumnWidth();
    clipBounds.width = Math.min(clipBounds.width, tableWidth);
    g.setClip(clipBounds);
    int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y));
    int  lastIndex = table.getRowCount()-1;
    Rectangle rowRect = new Rectangle(0,0,
      tableWidth, table.getRowHeight() + table.getRowMargin());
    rowRect.y = firstIndex*rowRect.height;
    for (int index = firstIndex; index <= lastIndex; index++) {
      if (rowRect.intersects(clipBounds)) {
        //System.out.println();                  // debug
        //System.out.print("" + index +": ");    // row
  paintRow(g, index);
      }
      rowRect.y += rowRect.height;
    }
    g.setClip(oldClipBounds);
  }
  private void paintRow(Graphics g, int row) {
    Rectangle rect = g.getClipBounds();
    boolean drawn  = false;
    
    AttributiveCellTableModel tableModel = (AttributiveCellTableModel)table.getModel();
    CellSpan cellAtt = (CellSpan)tableModel.getCellAttribute();
    int numColumns = table.getColumnCount();
    for (int column = 0; column < numColumns; column++) {
      Rectangle cellRect = table.getCellRect(row,column,true);
      int cellRow,cellColumn;
      if (cellAtt.isVisible(row,column)) {
  cellRow    = row;
  cellColumn = column;
    //  System.out.print("   "+column+" ");  // debug
      } else {
  cellRow    = row + cellAtt.getSpan(row,column)[CellSpan.ROW];
  cellColumn = column + cellAtt.getSpan(row,column)[CellSpan.COLUMN];
    //  System.out.print("  ("+column+")");  // debug
      }
      if (cellRect.intersects(rect)) {
  drawn = true;
  paintCell(g, cellRect, cellRow, cellColumn);
      } else {
  if (drawn) break;
      } 
    }
  }
  private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
    int spacingHeight = table.getRowMargin();
    int spacingWidth  = table.getColumnModel().getColumnMargin();
    Color c = g.getColor();
    g.setColor(table.getGridColor());
    g.drawRect(cellRect.x,cellRect.y,cellRect.width-1,cellRect.height-1);
    g.setColor(c);
    cellRect.setBounds(cellRect.x + spacingWidth/2, cellRect.y + spacingHeight/2,
           cellRect.width - spacingWidth, cellRect.height - spacingHeight);
    if (table.isEditing() && table.getEditingRow()==row &&
  table.getEditingColumn()==column) {
      Component component = table.getEditorComponent();
      component.setBounds(cellRect);
      component.validate();
    }
    else {
      TableCellRenderer renderer = table.getCellRenderer(row, column);
      Component component = table.prepareRenderer(renderer, row, column);
      if (component.getParent() == null) {
  rendererPane.add(component);
      }
      rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
          cellRect.width, cellRect.height, true);
    }
  }    
}

interface CellFont {
    
    public Font getFont(int row, int column);
    public void setFont(Font font, int row, int column);
    public void setFont(Font font, int[] rows, int[] columns);

}

interface ColoredCell {
    
    public Color getForeground(int row, int column);
    public void setForeground(Color color, int row, int column);
    public void setForeground(Color color, int[] rows, int[] columns);
    public Color getBackground(int row, int column);
    public void setBackground(Color color, int row, int column);
    public void setBackground(Color color, int[] rows, int[] columns);

}





MultiWidth Header Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
 *  (swing1.1beta3)
 * 
 * |-----------------------------------------------------|
 * |   1st  |      2nd        |          3rd             |
 * |-----------------------------------------------------|
 * |        |        |        |        |        |        |
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

/**
 * @version 1.0 11/09/98
 */
public class MultiWidthHeaderExample extends JFrame {
  MultiWidthHeaderExample() {
    super( "Multi-Width Header Example" );
    DefaultTableModel dm = new DefaultTableModel();
    dm.setDataVector(new Object[][]{
      {"a","b","c","d","e","f"},
      {"A","B","C","D","E","F"}},
    new Object[]{"1 st","","","","",""});
    JTable table = new JTable( dm ) {
      protected JTableHeader createDefaultTableHeader() {
  return new GroupableTableHeader(columnModel);
      }
    };
    TableColumnModel cm = table.getColumnModel();
    ColumnGroup g_2nd = new ColumnGroup("2 nd");
    g_2nd.add(cm.getColumn(1));
    g_2nd.add(cm.getColumn(2));
    ColumnGroup g_3rd = new ColumnGroup("3 rd");
    g_3rd.add(cm.getColumn(3));
    g_3rd.add(cm.getColumn(4));
    g_3rd.add(cm.getColumn(5));
    GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();
    header.addColumnGroup(g_2nd);
    header.addColumnGroup(g_3rd);
    JScrollPane scroll = new JScrollPane( table );
    getContentPane().add( scroll );
    setSize( 400, 100 );  
    header.revalidate(); 
  }
  public static void main(String[] args) {
    MultiWidthHeaderExample frame = new MultiWidthHeaderExample();
    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing( WindowEvent e ) {
  System.exit(0);
      }
    });
    frame.setVisible(true);
  }
}
/*
 * (swing1.1beta3)
 * 
 */
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

/**
  * ColumnGroup
  *
  * @version 1.0 10/20/98
  * @author Nobuo Tamemasa
  */
 
public class ColumnGroup {
  protected TableCellRenderer renderer;
  protected Vector v;
  protected String text;
  protected int margin=0;
  public ColumnGroup(String text) {
    this(null,text);
  }
  public ColumnGroup(TableCellRenderer renderer,String text) {
    if (renderer == null) {
      this.renderer = new DefaultTableCellRenderer() {
  public Component getTableCellRendererComponent(JTable table, Object value,
                         boolean isSelected, boolean hasFocus, int row, int column) {
    JTableHeader header = table.getTableHeader();
    if (header != null) {
      setForeground(header.getForeground());
      setBackground(header.getBackground());
      setFont(header.getFont());
    }
          setHorizontalAlignment(JLabel.CENTER);
          setText((value == null) ? "" : value.toString());
    setBorder(UIManager.getBorder("TableHeader.cellBorder"));
    return this;
        }
      };
    } else {
      this.renderer = renderer;
    }
    this.text = text;
    v = new Vector();
  }
  
  /**
   * @param obj    TableColumn or ColumnGroup
   */
  public void add(Object obj) {
    if (obj == null) { return; }
    v.addElement(obj);
  }
  
  /**
   * @param c    TableColumn
   * @param v    ColumnGroups
   */
  public Vector getColumnGroups(TableColumn c, Vector g) {
    g.addElement(this);
    if (v.contains(c)) return g;    
    Enumeration e = v.elements();
    while (e.hasMoreElements()) {
      Object obj = e.nextElement();
      if (obj instanceof ColumnGroup) {
        Vector groups = 
          (Vector)((ColumnGroup)obj).getColumnGroups(c,(Vector)g.clone());
        if (groups != null) return groups;
      }
    }
    return null;
  }
    
  public TableCellRenderer getHeaderRenderer() {
    return renderer;
  }
    
  public void setHeaderRenderer(TableCellRenderer renderer) {
    if (renderer != null) {
      this.renderer = renderer;
    }
  }
    
  public Object getHeaderValue() {
    return text;
  }
  
  public Dimension getSize(JTable table) {
    Component comp = renderer.getTableCellRendererComponent(
        table, getHeaderValue(), false, false,-1, -1);
    int height = comp.getPreferredSize().height; 
    int width  = 0;
    Enumeration e = v.elements();
    while (e.hasMoreElements()) {
      Object obj = e.nextElement();
      if (obj instanceof TableColumn) {
        TableColumn aColumn = (TableColumn)obj;
        width += aColumn.getWidth();
        width += margin;
      } else {
        width += ((ColumnGroup)obj).getSize(table).width;
      }
    }
    return new Dimension(width, height);
  }
  public void setColumnMargin(int margin) {
    this.margin = margin;
    Enumeration e = v.elements();
    while (e.hasMoreElements()) {
      Object obj = e.nextElement();
      if (obj instanceof ColumnGroup) {
        ((ColumnGroup)obj).setColumnMargin(margin);
      }
    }
  }
}
/*
 * (swing1.1beta3)
 * 
 */
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
 
/**
  * GroupableTableHeader
  *
  * @version 1.0 10/20/98
  * @author Nobuo Tamemasa
  */
public class GroupableTableHeader extends JTableHeader {
  private static final String uiClassID = "GroupableTableHeaderUI";
  protected Vector columnGroups = null;
    
  public GroupableTableHeader(TableColumnModel model) {
    super(model);
    setUI(new GroupableTableHeaderUI());
    setReorderingAllowed(false);
  }
  public void updateUI(){
   setUI(new GroupableTableHeaderUI());
  }
  
  public void setReorderingAllowed(boolean b) {
    reorderingAllowed = false;
  }
    
  public void addColumnGroup(ColumnGroup g) {
    if (columnGroups == null) {
      columnGroups = new Vector();
    }
    columnGroups.addElement(g);
  }
  public Enumeration getColumnGroups(TableColumn col) {
    if (columnGroups == null) return null;
    Enumeration e = columnGroups.elements();
    while (e.hasMoreElements()) {
      ColumnGroup cGroup = (ColumnGroup)e.nextElement();
      Vector v_ret = (Vector)cGroup.getColumnGroups(col,new Vector());
      if (v_ret != null) { 
  return v_ret.elements();
      }
    }
    return null;
  }
  
  public void setColumnMargin() {
    if (columnGroups == null) return;
    int columnMargin = getColumnModel().getColumnMargin();
    Enumeration e = columnGroups.elements();
    while (e.hasMoreElements()) {
      ColumnGroup cGroup = (ColumnGroup)e.nextElement();
      cGroup.setColumnMargin(columnMargin);
    }
  }
  
}
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.BasicTableHeaderUI;

public class GroupableTableHeaderUI extends BasicTableHeaderUI {
  
  public void paint(Graphics g, JComponent c) {
    Rectangle clipBounds = g.getClipBounds();
    if (header.getColumnModel() == null) return;
    ((GroupableTableHeader)header).setColumnMargin();
    int column = 0;
    Dimension size = header.getSize();
    Rectangle cellRect  = new Rectangle(0, 0, size.width, size.height);
    Hashtable h = new Hashtable();
    int columnMargin = header.getColumnModel().getColumnMargin();
    
    Enumeration enumeration = header.getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
      cellRect.height = size.height;
      cellRect.y      = 0;
      TableColumn aColumn = (TableColumn)enumeration.nextElement();
      Enumeration cGroups = ((GroupableTableHeader)header).getColumnGroups(aColumn);
      if (cGroups != null) {
        int groupHeight = 0;
        while (cGroups.hasMoreElements()) {
          ColumnGroup cGroup = (ColumnGroup)cGroups.nextElement();
          Rectangle groupRect = (Rectangle)h.get(cGroup);
          if (groupRect == null) {
            groupRect = new Rectangle(cellRect);
            Dimension d = cGroup.getSize(header.getTable());
            groupRect.width  = d.width;
            groupRect.height = d.height;    
            h.put(cGroup, groupRect);
          }
          paintCell(g, groupRect, cGroup);
          groupHeight += groupRect.height;
          cellRect.height = size.height - groupHeight;
          cellRect.y      = groupHeight;
        }
      }      
      cellRect.width = aColumn.getWidth() + columnMargin;
      if (cellRect.intersects(clipBounds)) {
        paintCell(g, cellRect, column);
      }
      cellRect.x += cellRect.width;
      column++;
    }
  }
  private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) {
    TableColumn aColumn = header.getColumnModel().getColumn(columnIndex);
    TableCellRenderer renderer = aColumn.getHeaderRenderer();
    //revised by jexp.ru
    renderer = new DefaultTableCellRenderer(){
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
          JLabel header = new JLabel();
            header.setForeground(table.getTableHeader().getForeground());
            header.setBackground(table.getTableHeader().getBackground());
            header.setFont(table.getTableHeader().getFont());
          header.setHorizontalAlignment(JLabel.CENTER);
          header.setText(value.toString());
          header.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
            return header;
        }
    
    };
    Component c = renderer.getTableCellRendererComponent(
        header.getTable(), aColumn.getHeaderValue(),false, false, -1, columnIndex);
        
    rendererPane.add(c);
    rendererPane.paintComponent(g, c, header, cellRect.x, cellRect.y,
        cellRect.width, cellRect.height, true);
  }
  private void paintCell(Graphics g, Rectangle cellRect,ColumnGroup cGroup) {
    TableCellRenderer renderer = cGroup.getHeaderRenderer();
      //revised by jexp.ru
     // if(renderer == null){
//      return ;
  //    }
    Component component = renderer.getTableCellRendererComponent(
      header.getTable(), cGroup.getHeaderValue(),false, false, -1, -1);
    rendererPane.add(component);
    rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
        cellRect.width, cellRect.height, true);
  }
  private int getHeaderHeight() {
    int height = 0;
    TableColumnModel columnModel = header.getColumnModel();
    for(int column = 0; column < columnModel.getColumnCount(); column++) {
      TableColumn aColumn = columnModel.getColumn(column);
      TableCellRenderer renderer = aColumn.getHeaderRenderer();
      //revised by jexp.ru
      if(renderer == null){
      return 16;
      }
      
      Component comp = renderer.getTableCellRendererComponent(
        header.getTable(), aColumn.getHeaderValue(), false, false,-1, column);
      int cHeight = comp.getPreferredSize().height;
      Enumeration e = ((GroupableTableHeader)header).getColumnGroups(aColumn);      
      if (e != null) {
        while (e.hasMoreElements()) {
          ColumnGroup cGroup = (ColumnGroup)e.nextElement();
          cHeight += cGroup.getSize(header.getTable()).height;
        }
      }
      height = Math.max(height, cHeight);
    }
    return height;
  }
  private Dimension createHeaderSize(long width) {
    TableColumnModel columnModel = header.getColumnModel();
    width += columnModel.getColumnMargin() * columnModel.getColumnCount();
    if (width > Integer.MAX_VALUE) {
      width = Integer.MAX_VALUE;
    }
    return new Dimension((int)width, getHeaderHeight());
  }
  public Dimension getPreferredSize(JComponent c) {
    long width = 0;
    Enumeration enumeration = header.getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
      TableColumn aColumn = (TableColumn)enumeration.nextElement();
      width = width + aColumn.getPreferredWidth();
    }
    return createHeaderSize(width);
  }
}





Pushable Table Header Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
/**
 * @version 1.0 02/25/99
 */
public class PushableHeaderExample extends JPanel {
  public PushableHeaderExample() {
    setLayout(new BorderLayout());
    String[] headerStr = { "Push", "me", "here" };
    DefaultTableModel dm = new DefaultTableModel(headerStr, 4);
    JTable table = new JTable(dm);
    ButtonHeaderRenderer renderer = new ButtonHeaderRenderer();
    TableColumnModel model = table.getColumnModel();
    int n = headerStr.length;
    for (int i = 0; i < n; i++) {
      model.getColumn(i).setHeaderRenderer(renderer);
    }
    JTableHeader header = table.getTableHeader();
    header.addMouseListener(new HeaderListener(header, renderer));
    JScrollPane pane = new JScrollPane(table);
    add(pane, BorderLayout.CENTER);
  }
  public static void main(String[] args) {
    JFrame f = new JFrame("PushableHeaderTable Example");
    f.getContentPane()
        .add(new PushableHeaderExample(), BorderLayout.CENTER);
    f.setSize(400, 100);
    f.setVisible(true);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
  class HeaderListener extends MouseAdapter {
    JTableHeader header;
    ButtonHeaderRenderer renderer;
    HeaderListener(JTableHeader header, ButtonHeaderRenderer renderer) {
      this.header = header;
      this.renderer = renderer;
    }
    public void mousePressed(MouseEvent e) {
      int col = header.columnAtPoint(e.getPoint());
      renderer.setPressedColumn(col);
      header.repaint();
      System.out.println("Ouch! " + col);
    }
    public void mouseReleased(MouseEvent e) {
      int col = header.columnAtPoint(e.getPoint());
      renderer.setPressedColumn(-1); // clear
      header.repaint();
    }
  }
  class ButtonHeaderRenderer extends JButton implements TableCellRenderer {
    int pushedColumn;
    public ButtonHeaderRenderer() {
      pushedColumn = -1;
      setMargin(new Insets(0, 0, 0, 0));
    }
    public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column) {
      setText((value == null) ? "" : value.toString());
      boolean isPressed = (column == pushedColumn);
      getModel().setPressed(isPressed);
      getModel().setArmed(isPressed);
      return this;
    }
    public void setPressedColumn(int col) {
      pushedColumn = col;
    }
  }
}





Radio Button Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/**
 * @version 1.0 12/03/98
 */
import java.awt.ruponent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ButtonGroup;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
class RadioButtonRenderer implements TableCellRenderer {
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    if (value == null)
      return null;
    return (Component) value;
  }
}
class RadioButtonEditor extends DefaultCellEditor implements ItemListener {
  private JRadioButton button;
  public RadioButtonEditor(JCheckBox checkBox) {
    super(checkBox);
  }
  public Component getTableCellEditorComponent(JTable table, Object value,
      boolean isSelected, int row, int column) {
    if (value == null)
      return null;
    button = (JRadioButton) value;
    button.addItemListener(this);
    return (Component) value;
  }
  public Object getCellEditorValue() {
    button.removeItemListener(this);
    return button;
  }
  public void itemStateChanged(ItemEvent e) {
    super.fireEditingStopped();
  }
}
public class JRadioButtonTableExample extends JFrame {
  public JRadioButtonTableExample() {
    super("JRadioButtonTable Example");
    UIDefaults ui = UIManager.getLookAndFeel().getDefaults();
    UIManager.put("RadioButton.focus", ui.getColor("control"));
    DefaultTableModel dm = new DefaultTableModel();
    dm.setDataVector(new Object[][] { { "Group 1", new JRadioButton("A") },
        { "Group 1", new JRadioButton("B") },
        { "Group 1", new JRadioButton("C") },
        { "Group 2", new JRadioButton("a") },
        { "Group 2", new JRadioButton("b") } }, new Object[] {
        "String", "JRadioButton" });
    JTable table = new JTable(dm) {
      public void tableChanged(TableModelEvent e) {
        super.tableChanged(e);
        repaint();
      }
    };
    ButtonGroup group1 = new ButtonGroup();
    group1.add((JRadioButton) dm.getValueAt(0, 1));
    group1.add((JRadioButton) dm.getValueAt(1, 1));
    group1.add((JRadioButton) dm.getValueAt(2, 1));
    ButtonGroup group2 = new ButtonGroup();
    group2.add((JRadioButton) dm.getValueAt(3, 1));
    group2.add((JRadioButton) dm.getValueAt(4, 1));
    table.getColumn("JRadioButton").setCellRenderer(
        new RadioButtonRenderer());
    table.getColumn("JRadioButton").setCellEditor(
        new RadioButtonEditor(new JCheckBox()));
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll);
    setSize(200, 140);
    setVisible(true);
  }
  public static void main(String[] args) {
    JRadioButtonTableExample frame = new JRadioButtonTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}





RadioButton Table Example 2

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1) */

import java.awt.ruponent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
 * @version 1.2 08/13/99
 */
public class JRadioButtonTableExample2 extends JFrame {
  public JRadioButtonTableExample2() {
    super("JRadioButtonTable Example");
    DefaultTableModel dm = new DefaultTableModel();
    dm.setDataVector(new Object[][] { { "1", new Integer(-1) },
        { "2", new Integer(-1) }, { "3", new Integer(0) },
        { "4", new Integer(1) }, { "5", new Integer(2) } },
        new Object[] { "Question", "Answer" });
    JTable table = new JTable(dm);
    String[] answer = { "A", "B", "C" };
    table.getColumn("Answer").setCellRenderer(
        new RadioButtonRenderer(answer));
    table.getColumn("Answer").setCellEditor(
        new RadioButtonEditor(new JCheckBox(), new RadioButtonPanel(
            answer)));
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add(scroll);
  }
  // Cell base
  class RadioButtonPanel extends JPanel {
    JRadioButton[] buttons;
    RadioButtonPanel(String[] str) {
      setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
      buttons = new JRadioButton[str.length];
      for (int i = 0; i < buttons.length; i++) {
        buttons[i] = new JRadioButton(str[i]);
        buttons[i].setFocusPainted(false);
        add(buttons[i]);
      }
    }
    public void setSelectedIndex(int index) {
      for (int i = 0; i < buttons.length; i++) {
        buttons[i].setSelected(i == index);
      }
    }
    public int getSelectedIndex() {
      for (int i = 0; i < buttons.length; i++) {
        if (buttons[i].isSelected()) {
          return i;
        }
      }
      return -1;
    }
    public JRadioButton[] getButtons() {
      return buttons;
    }
  }
  class RadioButtonRenderer extends RadioButtonPanel implements
      TableCellRenderer {
    RadioButtonRenderer(String[] strs) {
      super(strs);
    }
    public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column) {
      if (value instanceof Integer) {
        setSelectedIndex(((Integer) value).intValue());
      }
      return this;
    }
  }
  class RadioButtonEditor extends DefaultCellEditor implements ItemListener {
    RadioButtonPanel panel;
    public RadioButtonEditor(JCheckBox checkBox, RadioButtonPanel panel) {
      super(checkBox);
      this.panel = panel;
      ButtonGroup buttonGroup = new ButtonGroup();
      JRadioButton[] buttons = panel.getButtons();
      for (int i = 0; i < buttons.length; i++) {
        buttonGroup.add(buttons[i]);
        buttons[i].addItemListener(this);
      }
    }
    public Component getTableCellEditorComponent(JTable table,
        Object value, boolean isSelected, int row, int column) {
      if (value instanceof Integer) {
        panel.setSelectedIndex(((Integer) value).intValue());
      }
      return panel;
    }
    public Object getCellEditorValue() {
      return new Integer(panel.getSelectedIndex());
    }
    public void itemStateChanged(ItemEvent e) {
      super.fireEditingStopped();
    }
  }
  public static void main(String[] args) {
    JRadioButtonTableExample2 frame = new JRadioButtonTableExample2();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setSize(230, 140);
    frame.setVisible(true);
  }
}





Sortable Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Hashtable;
import java.util.Locale;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
/**
 * @version 1.0 02/25/99
 */
public class SortableTableExample extends JPanel {
  public SortableTableExample() {
    setLayout(new BorderLayout());
    String[] headerStr = { "Name", "Date", "Size", "Dir" };
    int[] columnWidth = { 100, 150, 100, 50 };
    SortableTableModel dm = new SortableTableModel() {
      public Class getColumnClass(int col) {
        switch (col) {
        case 0:
          return String.class;
        case 1:
          return Date.class;
        case 2:
          return Integer.class;
        case 3:
          return Boolean.class;
        default:
          return Object.class;
        }
      }
      public boolean isCellEditable(int row, int col) {
        switch (col) {
        case 1:
          return false;
        default:
          return true;
        }
      }
      public void setValueAt(Object obj, int row, int col) {
        switch (col) {
        case 2:
          super.setValueAt(new Integer(obj.toString()), row, col);
          return;
        default:
          super.setValueAt(obj, row, col);
          return;
        }
      }
    };
    dm
        .setDataVector(
            new Object[][] {
                { "b", getDate("98/12/02"), new Integer(14),
                    new Boolean(false) },
                { "a", getDate("99/01/01"), new Integer(67),
                    new Boolean(false) },
                { "d", getDate("99/02/11"), new Integer(2),
                    new Boolean(false) },
                { "c", getDate("99/02/27"), new Integer(7),
                    new Boolean(false) },
                { "foo", new Date(), new Integer(5),
                    new Boolean(true) },
                { "bar", new Date(), new Integer(10),
                    new Boolean(true) } }, headerStr);
    JTable table = new JTable(dm);
    //table.setShowGrid(false);
    table.setShowVerticalLines(true);
    table.setShowHorizontalLines(false);
    SortButtonRenderer renderer = new SortButtonRenderer();
    TableColumnModel model = table.getColumnModel();
    int n = headerStr.length;
    for (int i = 0; i < n; i++) {
      model.getColumn(i).setHeaderRenderer(renderer);
      model.getColumn(i).setPreferredWidth(columnWidth[i]);
    }
    JTableHeader header = table.getTableHeader();
    header.addMouseListener(new HeaderListener(header, renderer));
    JScrollPane pane = new JScrollPane(table);
    add(pane, BorderLayout.CENTER);
  }
  public static void main(String[] args) {
    JFrame f = new JFrame("SortableTable Example");
    f.getContentPane().add(new SortableTableExample(), BorderLayout.CENTER);
    f.setSize(400, 160);
    f.setVisible(true);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
  private static DateFormat dateFormat = DateFormat.getDateInstance(
      DateFormat.SHORT, Locale.JAPAN);
  private static Date getDate(String dateString) {
    Date date = null;
    try {
      date = dateFormat.parse(dateString);
    } catch (ParseException ex) {
      date = new Date();
    }
    return date;
  }
  class HeaderListener extends MouseAdapter {
    JTableHeader header;
    SortButtonRenderer renderer;
    HeaderListener(JTableHeader header, SortButtonRenderer renderer) {
      this.header = header;
      this.renderer = renderer;
    }
    public void mousePressed(MouseEvent e) {
      int col = header.columnAtPoint(e.getPoint());
      int sortCol = header.getTable().convertColumnIndexToModel(col);
      renderer.setPressedColumn(col);
      renderer.setSelectedColumn(col);
      header.repaint();
      if (header.getTable().isEditing()) {
        header.getTable().getCellEditor().stopCellEditing();
      }
      boolean isAscent;
      if (SortButtonRenderer.DOWN == renderer.getState(col)) {
        isAscent = true;
      } else {
        isAscent = false;
      }
      ((SortableTableModel) header.getTable().getModel()).sortByColumn(
          sortCol, isAscent);
    }
    public void mouseReleased(MouseEvent e) {
      int col = header.columnAtPoint(e.getPoint());
      renderer.setPressedColumn(-1); // clear
      header.repaint();
    }
  }
}
class SortableTableModel extends DefaultTableModel {
  int[] indexes;
  TableSorter sorter;
  public SortableTableModel() {
  }
  public Object getValueAt(int row, int col) {
    int rowIndex = row;
    if (indexes != null) {
      rowIndex = indexes[row];
    }
    return super.getValueAt(rowIndex, col);
  }
  public void setValueAt(Object value, int row, int col) {
    int rowIndex = row;
    if (indexes != null) {
      rowIndex = indexes[row];
    }
    super.setValueAt(value, rowIndex, col);
  }
  public void sortByColumn(int column, boolean isAscent) {
    if (sorter == null) {
      sorter = new TableSorter(this);
    }
    sorter.sort(column, isAscent);
    fireTableDataChanged();
  }
  public int[] getIndexes() {
    int n = getRowCount();
    if (indexes != null) {
      if (indexes.length == n) {
        return indexes;
      }
    }
    indexes = new int[n];
    for (int i = 0; i < n; i++) {
      indexes[i] = i;
    }
    return indexes;
  }
}
class TableSorter {
  SortableTableModel model;
  public TableSorter(SortableTableModel model) {
    this.model = model;
  }
  //n2 selection
  public void sort(int column, boolean isAscent) {
    int n = model.getRowCount();
    int[] indexes = model.getIndexes();
    for (int i = 0; i < n - 1; i++) {
      int k = i;
      for (int j = i + 1; j < n; j++) {
        if (isAscent) {
          if (compare(column, j, k) < 0) {
            k = j;
          }
        } else {
          if (compare(column, j, k) > 0) {
            k = j;
          }
        }
      }
      int tmp = indexes[i];
      indexes[i] = indexes[k];
      indexes[k] = tmp;
    }
  }
  // comparaters
  public int compare(int column, int row1, int row2) {
    Object o1 = model.getValueAt(row1, column);
    Object o2 = model.getValueAt(row2, column);
    if (o1 == null && o2 == null) {
      return 0;
    } else if (o1 == null) {
      return -1;
    } else if (o2 == null) {
      return 1;
    } else {
      Class type = model.getColumnClass(column);
      if (type.getSuperclass() == Number.class) {
        return compare((Number) o1, (Number) o2);
      } else if (type == String.class) {
        return ((String) o1).rupareTo((String) o2);
      } else if (type == Date.class) {
        return compare((Date) o1, (Date) o2);
      } else if (type == Boolean.class) {
        return compare((Boolean) o1, (Boolean) o2);
      } else {
        return ((String) o1).rupareTo((String) o2);
      }
    }
  }
  public int compare(Number o1, Number o2) {
    double n1 = o1.doubleValue();
    double n2 = o2.doubleValue();
    if (n1 < n2) {
      return -1;
    } else if (n1 > n2) {
      return 1;
    } else {
      return 0;
    }
  }
  public int compare(Date o1, Date o2) {
    long n1 = o1.getTime();
    long n2 = o2.getTime();
    if (n1 < n2) {
      return -1;
    } else if (n1 > n2) {
      return 1;
    } else {
      return 0;
    }
  }
  public int compare(Boolean o1, Boolean o2) {
    boolean b1 = o1.booleanValue();
    boolean b2 = o2.booleanValue();
    if (b1 == b2) {
      return 0;
    } else if (b1) {
      return 1;
    } else {
      return -1;
    }
  }
}
class SortButtonRenderer extends JButton implements TableCellRenderer {
  public static final int NONE = 0;
  public static final int DOWN = 1;
  public static final int UP = 2;
  int pushedColumn;
  Hashtable state;
  JButton downButton, upButton;
  public SortButtonRenderer() {
    pushedColumn = -1;
    state = new Hashtable();
    setMargin(new Insets(0, 0, 0, 0));
    setHorizontalTextPosition(LEFT);
    setIcon(new BlankIcon());
    // perplexed
    // ArrowIcon(SwingConstants.SOUTH, true)
    // BevelArrowIcon (int direction, boolean isRaisedView, boolean
    // isPressedView)
    downButton = new JButton();
    downButton.setMargin(new Insets(0, 0, 0, 0));
    downButton.setHorizontalTextPosition(LEFT);
    downButton
        .setIcon(new BevelArrowIcon(BevelArrowIcon.DOWN, false, false));
    downButton.setPressedIcon(new BevelArrowIcon(BevelArrowIcon.DOWN,
        false, true));
    upButton = new JButton();
    upButton.setMargin(new Insets(0, 0, 0, 0));
    upButton.setHorizontalTextPosition(LEFT);
    upButton.setIcon(new BevelArrowIcon(BevelArrowIcon.UP, false, false));
    upButton.setPressedIcon(new BevelArrowIcon(BevelArrowIcon.UP, false,
        true));
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    JButton button = this;
    Object obj = state.get(new Integer(column));
    if (obj != null) {
      if (((Integer) obj).intValue() == DOWN) {
        button = downButton;
      } else {
        button = upButton;
      }
    }
    button.setText((value == null) ? "" : value.toString());
    boolean isPressed = (column == pushedColumn);
    button.getModel().setPressed(isPressed);
    button.getModel().setArmed(isPressed);
    return button;
  }
  public void setPressedColumn(int col) {
    pushedColumn = col;
  }
  public void setSelectedColumn(int col) {
    if (col < 0)
      return;
    Integer value = null;
    Object obj = state.get(new Integer(col));
    if (obj == null) {
      value = new Integer(DOWN);
    } else {
      if (((Integer) obj).intValue() == DOWN) {
        value = new Integer(UP);
      } else {
        value = new Integer(DOWN);
      }
    }
    state.clear();
    state.put(new Integer(col), value);
  }
  public int getState(int col) {
    int retValue;
    Object obj = state.get(new Integer(col));
    if (obj == null) {
      retValue = NONE;
    } else {
      if (((Integer) obj).intValue() == DOWN) {
        retValue = DOWN;
      } else {
        retValue = UP;
      }
    }
    return retValue;
  }
}
class BevelArrowIcon implements Icon {
  public static final int UP = 0; // direction
  public static final int DOWN = 1;
  private static final int DEFAULT_SIZE = 11;
  private Color edge1;
  private Color edge2;
  private Color fill;
  private int size;
  private int direction;
  public BevelArrowIcon(int direction, boolean isRaisedView,
      boolean isPressedView) {
    if (isRaisedView) {
      if (isPressedView) {
        init(UIManager.getColor("controlLtHighlight"), UIManager
            .getColor("controlDkShadow"), UIManager
            .getColor("controlShadow"), DEFAULT_SIZE, direction);
      } else {
        init(UIManager.getColor("controlHighlight"), UIManager
            .getColor("controlShadow"), UIManager
            .getColor("control"), DEFAULT_SIZE, direction);
      }
    } else {
      if (isPressedView) {
        init(UIManager.getColor("controlDkShadow"), UIManager
            .getColor("controlLtHighlight"), UIManager
            .getColor("controlShadow"), DEFAULT_SIZE, direction);
      } else {
        init(UIManager.getColor("controlShadow"), UIManager
            .getColor("controlHighlight"), UIManager
            .getColor("control"), DEFAULT_SIZE, direction);
      }
    }
  }
  public BevelArrowIcon(Color edge1, Color edge2, Color fill, int size,
      int direction) {
    init(edge1, edge2, fill, size, direction);
  }
  public void paintIcon(Component c, Graphics g, int x, int y) {
    switch (direction) {
    case DOWN:
      drawDownArrow(g, x, y);
      break;
    case UP:
      drawUpArrow(g, x, y);
      break;
    }
  }
  public int getIconWidth() {
    return size;
  }
  public int getIconHeight() {
    return size;
  }
  private void init(Color edge1, Color edge2, Color fill, int size,
      int direction) {
    this.edge1 = edge1;
    this.edge2 = edge2;
    this.fill = fill;
    this.size = size;
    this.direction = direction;
  }
  private void drawDownArrow(Graphics g, int xo, int yo) {
    g.setColor(edge1);
    g.drawLine(xo, yo, xo + size - 1, yo);
    g.drawLine(xo, yo + 1, xo + size - 3, yo + 1);
    g.setColor(edge2);
    g.drawLine(xo + size - 2, yo + 1, xo + size - 1, yo + 1);
    int x = xo + 1;
    int y = yo + 2;
    int dx = size - 6;
    while (y + 1 < yo + size) {
      g.setColor(edge1);
      g.drawLine(x, y, x + 1, y);
      g.drawLine(x, y + 1, x + 1, y + 1);
      if (0 < dx) {
        g.setColor(fill);
        g.drawLine(x + 2, y, x + 1 + dx, y);
        g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
      }
      g.setColor(edge2);
      g.drawLine(x + dx + 2, y, x + dx + 3, y);
      g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
      x += 1;
      y += 2;
      dx -= 2;
    }
    g.setColor(edge1);
    g.drawLine(xo + (size / 2), yo + size - 1, xo + (size / 2), yo + size
        - 1);
  }
  private void drawUpArrow(Graphics g, int xo, int yo) {
    g.setColor(edge1);
    int x = xo + (size / 2);
    g.drawLine(x, yo, x, yo);
    x--;
    int y = yo + 1;
    int dx = 0;
    while (y + 3 < yo + size) {
      g.setColor(edge1);
      g.drawLine(x, y, x + 1, y);
      g.drawLine(x, y + 1, x + 1, y + 1);
      if (0 < dx) {
        g.setColor(fill);
        g.drawLine(x + 2, y, x + 1 + dx, y);
        g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
      }
      g.setColor(edge2);
      g.drawLine(x + dx + 2, y, x + dx + 3, y);
      g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
      x -= 1;
      y += 2;
      dx += 2;
    }
    g.setColor(edge1);
    g.drawLine(xo, yo + size - 3, xo + 1, yo + size - 3);
    g.setColor(edge2);
    g.drawLine(xo + 2, yo + size - 2, xo + size - 1, yo + size - 2);
    g.drawLine(xo, yo + size - 1, xo + size, yo + size - 1);
  }
}
class BlankIcon implements Icon {
  private Color fillColor;
  private int size;
  public BlankIcon() {
    this(null, 11);
  }
  public BlankIcon(Color color, int size) {
    //UIManager.getColor("control")
    //UIManager.getColor("controlShadow")
    fillColor = color;
    this.size = size;
  }
  public void paintIcon(Component c, Graphics g, int x, int y) {
    if (fillColor != null) {
      g.setColor(fillColor);
      g.drawRect(x, y, size - 1, size - 1);
    }
  }
  public int getIconWidth() {
    return size;
  }
  public int getIconHeight() {
    return size;
  }
}





Striped Currency Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class StripedCurrencyTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Striped Currency Table");
    JTable tbl = new JTable(new CurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tbl.setShowHorizontalLines(false);
    // Add the stripe renderer.
    StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
        Color.white, null, null);
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon)value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}





Swing Table in ComboBox

 
(From http://swinglabs.org/downloads.jsp)





Tabbable Currency Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.EventObject;
import java.util.Vector;
import javax.swing.CellEditor;
import javax.swing.FocusManager;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
public class TabbableCurrencyTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Tabbable Currency Table");
    TabEditTable tbl = new TabEditTable(
        new TestUpdatableCurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tbl.setShowHorizontalLines(false);
    tbl.setIntercellSpacing(new Dimension(1, 0));
    // Add the stripe renderer in the leftmost four columns.
    StripedTableCellRenderer.installInColumn(tbl, 0, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 1, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 2, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 3, Color.lightGray,
        Color.white, null, null);
    // Add the highlight renderer to the difference column.
    // The following comparator makes it highlight
    // cells with negative numeric values.
    Comparator cmp = new Comparator() {
      public boolean shouldHighlight(JTable tbl, Object value, int row,
          int column) {
        if (value instanceof Number) {
          double columnValue = ((Number) value).doubleValue();
          return columnValue < (double) 0.0;
        }
        return false;
      }
    };
    tcm.getColumn(3).setCellRenderer(
        new HighlightRenderer(cmp, null, Color.pink, Color.black,
            Color.pink.darker(), Color.white));
    // Install a button renderer in the last column
    ButtonRenderer buttonRenderer = new ButtonRenderer();
    buttonRenderer.setForeground(Color.blue);
    buttonRenderer.setBackground(Color.lightGray);
    tcm.getColumn(4).setCellRenderer(buttonRenderer);
    // Install a button editor in the last column
    TableCellEditor editor = new ButtonEditor(new JButton());
    tcm.getColumn(4).setCellEditor(editor);
    // Install the list of columns containing tabbable editors
    tbl.setEditingColumns(new int[] { 1, 2 });
    // Make the rows wide enough to take the buttons
    tbl.setRowHeight(20);
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class TabEditTable extends JTable {
  public TabEditTable() {
    super();
  }
  public TabEditTable(TableModel dm) {
    super(dm);
  }
  public TabEditTable(TableModel dm, TableColumnModel cm) {
    super(dm, cm);
  }
  public TabEditTable(TableModel dm, TableColumnModel cm,
      ListSelectionModel sm) {
    super(dm, cm, sm);
  }
  public TabEditTable(int numRows, int numColumns) {
    super(numRows, numColumns);
  }
  public TabEditTable(final Vector rowData, final Vector columnNames) {
    super(rowData, columnNames);
  }
  public TabEditTable(final Object[][] rowData, final Object[] columnNames) {
    super(rowData, columnNames);
  }
  // Set the columns that contain tabbable editors
  public void setEditingColumns(int[] columns) {
    editingColumns = columns;
    convertEditableColumnsToView();
  }
  public int[] getEditingColumns() {
    return editingColumns;
  }
  // Overrides of JTable methods
  public boolean editCellAt(int row, int column, EventObject evt) {
    if (super.editCellAt(row, column, evt) == false) {
      return false;
    }
    if (viewEditingColumns != null) {
      // Note: column is specified in terms of the column model
      int length = viewEditingColumns.length;
      for (int i = 0; i < length; i++) {
        if (column == viewEditingColumns[i]) {
          Component comp = getEditorComponent();
          comp.addKeyListener(tabKeyListener);
          this.addKeyListener(tabKeyListener);
          focusManager = FocusManager.getCurrentManager();
          FocusManager.disableSwingFocusManager();
          inTabbingEditor = true;
          comp.requestFocus();
          break;
        }
      }
    }
    return true;
  }
  public void editingStopped(ChangeEvent evt) {
    if (inTabbingEditor == true) {
      Component comp = getEditorComponent();
      comp.removeKeyListener(tabKeyListener);
      this.removeKeyListener(tabKeyListener);
      FocusManager.setCurrentManager(focusManager);
      inTabbingEditor = false;
    }
    super.editingStopped(evt);
  }
  protected void convertEditableColumnsToView() {
    // Convert the editable columns to view column numbers
    if (editingColumns == null) {
      viewEditingColumns = null;
      return;
    }
    // Create a set of editable columns in terms of view
    // column numbers in ascending order. Note that not all
    // editable columns in the data model need be visible.
    int length = editingColumns.length;
    viewEditingColumns = new int[length];
    int nextSlot = 0;
    for (int i = 0; i < length; i++) {
      int viewIndex = convertColumnIndexToView(editingColumns[i]);
      if (viewIndex != -1) {
        viewEditingColumns[nextSlot++] = viewIndex;
      }
    }
    // Now create an array of the right length to hold the view indices
    if (nextSlot < length) {
      int[] tempArray = new int[nextSlot];
      System.arraycopy(viewEditingColumns, 0, tempArray, 0, nextSlot);
      viewEditingColumns = tempArray;
    }
    // Finally, sort the view columns into order
    TableUtilities.sort(viewEditingColumns);
  }
  protected void moveToNextEditor(int row, int column, boolean forward) {
    // Column is specified in terms of the column model
    if (viewEditingColumns != null) {
      int length = viewEditingColumns.length;
      // Move left-to-right or right-to-left across the table
      for (int i = 0; i < length; i++) {
        if (viewEditingColumns[i] == column) {
          // Select the next column to edit
          if (forward == true) {
            if (++i == length) {
              // Reached end of row - wrap
              i = 0;
              row++;
              if (row == getRowCount()) {
                // End of table - wrap
                row = 0;
              }
            }
          } else {
            if (--i < 0) {
              i = length - 1;
              row--;
              if (row < 0) {
                row = getRowCount() - 1;
              }
            }
          }
          final int newRow = row;
          final int newColumn = viewEditingColumns[i];
          // Start editing at new location
          SwingUtilities.invokeLater(new Runnable() {
            public void run() {
              editCellAt(newRow, newColumn);
              ListSelectionModel rowSel = getSelectionModel();
              ListSelectionModel columnSel = getColumnModel()
                  .getSelectionModel();
              rowSel.setSelectionInterval(newRow, newRow);
              columnSel
                  .setSelectionInterval(newColumn, newColumn);
            }
          });
          break;
        }
      }
    }
  }
  // Catch changes to the table column model
  public void columnAdded(TableColumnModelEvent e) {
    super.columnAdded(e);
    convertEditableColumnsToView();
  }
  public void columnRemoved(TableColumnModelEvent e) {
    super.columnRemoved(e);
    convertEditableColumnsToView();
  }
  public void columnMoved(TableColumnModelEvent e) {
    super.columnMoved(e);
    convertEditableColumnsToView();
  }
  public class TabKeyListener extends KeyAdapter {
    public void keyPressed(KeyEvent evt) {
      if (evt.getKeyCode() == KeyEvent.VK_TAB) {
        if (inTabbingEditor == true) {
          TableCellEditor editor = getCellEditor();
          int editRow = getEditingRow();
          int editColumn = getEditingColumn();
          if (editor != null) {
            boolean stopped = editor.stopCellEditing();
            if (stopped == true) {
              boolean forward = (evt.isShiftDown() == false);
              moveToNextEditor(editRow, editColumn, forward);
            }
          }
        }
      }
    }
  }
  protected boolean inTabbingEditor;
  protected FocusManager focusManager;
  protected int[] editingColumns; // Model columns
  protected int[] viewEditingColumns; // View columns
  protected TabKeyListener tabKeyListener = new TabKeyListener();
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon) value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class TableUtilities {
  // Calculate the required width of a table column
  public static int calculateColumnWidth(JTable table, int columnIndex) {
    int width = 0; // The return value
    int rowCount = table.getRowCount();
    for (int i = 0; i < rowCount; i++) {
      TableCellRenderer renderer = table.getCellRenderer(i, columnIndex);
      Component comp = renderer.getTableCellRendererComponent(table,
          table.getValueAt(i, columnIndex), false, false, i,
          columnIndex);
      int thisWidth = comp.getPreferredSize().width;
      if (thisWidth > width) {
        width = thisWidth;
      }
    }
    return width;
  }
  // Set the widths of every column in a table
  public static void setColumnWidths(JTable table, Insets insets,
      boolean setMinimum, boolean setMaximum) {
    int columnCount = table.getColumnCount();
    TableColumnModel tcm = table.getColumnModel();
    int spare = (insets == null ? 0 : insets.left + insets.right);
    for (int i = 0; i < columnCount; i++) {
      int width = calculateColumnWidth(table, i);
      width += spare;
      TableColumn column = tcm.getColumn(i);
      column.setPreferredWidth(width);
      if (setMinimum == true) {
        column.setMinWidth(width);
      }
      if (setMaximum == true) {
        column.setMaxWidth(width);
      }
    }
  }
  // Sort an array of integers in place
  public static void sort(int[] values) {
    int length = values.length;
    if (length > 1) {
      for (int i = 0; i < length - 1; i++) {
        for (int j = i + 1; j < length; j++) {
          if (values[j] < values[i]) {
            int temp = values[i];
            values[i] = values[j];
            values[j] = temp;
          }
        }
      }
    }
  }
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}
class HighlightRenderer implements TableCellRenderer {
  public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
      Color backColor, Color foreColor, Color highlightBack,
      Color highlightFore) {
    this.cmp = cmp;
    this.targetRenderer = targetRenderer;
    this.backColor = backColor;
    this.foreColor = foreColor;
    this.highlightBack = highlightBack;
    this.highlightFore = highlightFore;
  }
  public Component getTableCellRendererComponent(JTable tbl, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
    }
    Component comp = renderer.getTableCellRendererComponent(tbl, value,
        isSelected, hasFocus, row, column);
    if (isSelected == false && hasFocus == false && value != null) {
      if (cmp.shouldHighlight(tbl, value, row, column)) {
        comp.setForeground(highlightFore);
        comp.setBackground(highlightBack);
      } else {
        comp.setForeground(foreColor);
        comp.setBackground(backColor);
      }
    }
    return comp;
  }
  protected Comparator cmp;
  protected TableCellRenderer targetRenderer;
  protected Color backColor;
  protected Color foreColor;
  protected Color highlightBack;
  protected Color highlightFore;
}
interface Comparator {
  public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
      int column);
}
class ButtonRenderer extends JButton implements TableCellRenderer {
  public ButtonRenderer() {
    this.border = getBorder();
    this.setOpaque(true);
  }
  public void setForeground(Color foreground) {
    this.foreground = foreground;
    super.setForeground(foreground);
  }
  public void setBackground(Color background) {
    this.background = background;
    super.setBackground(background);
  }
  public void setFont(Font font) {
    this.font = font;
    super.setFont(font);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    Color cellForeground = foreground != null ? foreground : table
        .getForeground();
    Color cellBackground = background != null ? background : table
        .getBackground();
    setFont(font != null ? font : table.getFont());
    if (hasFocus) {
      setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      if (table.isCellEditable(row, column)) {
        cellForeground = UIManager
            .getColor("Table.focusCellForeground");
        cellBackground = UIManager
            .getColor("Table.focusCellBackground");
      }
    } else {
      setBorder(border);
    }
    super.setForeground(cellForeground);
    super.setBackground(cellBackground);
    // Customize the component"s appearance
    setValue(value);
    return this;
  }
  protected void setValue(Object value) {
    if (value == null) {
      setText("");
      setIcon(null);
    } else if (value instanceof Icon) {
      setText("");
      setIcon((Icon) value);
    } else if (value instanceof DataWithIcon) {
      DataWithIcon d = (DataWithIcon) value;
      setText(d.toString());
      setIcon(d.getIcon());
    } else {
      setText(value.toString());
      setIcon(null);
    }
  }
  protected Color foreground;
  protected Color background;
  protected Font font;
  protected Border border;
}
class ButtonEditor extends BasicCellEditor implements ActionListener,
    TableCellEditor {
  public ButtonEditor(JButton button) {
    super(button);
    button.addActionListener(this);
  }
  public void setForeground(Color foreground) {
    this.foreground = foreground;
    editor.setForeground(foreground);
  }
  public void setBackground(Color background) {
    this.background = background;
    editor.setBackground(background);
  }
  public void setFont(Font font) {
    this.font = font;
    editor.setFont(font);
  }
  public Object getCellEditorValue() {
    return value;
  }
  public void editingStarted(EventObject event) {
    // Edit starting - click the button if necessary
    if (!(event instanceof MouseEvent)) {
      // Keyboard event - click the button
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          ((JButton) editor).doClick();
        }
      });
    }
  }
  public Component getTableCellEditorComponent(JTable tbl, Object value,
      boolean isSelected, int row, int column) {
    editor.setForeground(foreground != null ? foreground : tbl
        .getForeground());
    editor.setBackground(background != null ? background : tbl
        .getBackground());
    editor.setFont(font != null ? font : tbl.getFont());
    this.value = value;
    setValue(value);
    return editor;
  }
  protected void setValue(Object value) {
    JButton button = (JButton) editor;
    if (value == null) {
      button.setText("");
      button.setIcon(null);
    } else if (value instanceof Icon) {
      button.setText("");
      button.setIcon((Icon) value);
    } else if (value instanceof DataWithIcon) {
      DataWithIcon d = (DataWithIcon) value;
      button.setText(d.toString());
      button.setIcon(d.getIcon());
    } else {
      button.setText(value.toString());
      button.setIcon(null);
    }
  }
  public void actionPerformed(ActionEvent evt) {
    // Button pressed - stop the edit
    stopCellEditing();
  }
  protected Object value;
  protected Color foreground;
  protected Color background;
  protected Font font;
}
class BasicCellEditor implements CellEditor, PropertyChangeListener {
  public BasicCellEditor() {
    this.editor = null;
  }
  public BasicCellEditor(JComponent editor) {
    this.editor = editor;
    editor.addPropertyChangeListener(this);
  }
  public Object getCellEditorValue() {
    return null;
  }
  public boolean isCellEditable(EventObject evt) {
    editingEvent = evt;
    return true;
  }
  public boolean shouldSelectCell(EventObject evt) {
    return true;
  }
  public boolean stopCellEditing() {
    fireEditingStopped();
    return true;
  }
  public void cancelCellEditing() {
    fireEditingCanceled();
  }
  public void addCellEditorListener(CellEditorListener l) {
    listeners.add(CellEditorListener.class, l);
  }
  public void removeCellEditorListener(CellEditorListener l) {
    listeners.remove(CellEditorListener.class, l);
  }
  // Returns the editing component
  public JComponent getComponent() {
    return editor;
  }
  // Sets the editing component
  public void setComponent(JComponent comp) {
    editor = comp;
  }
  // Returns the event that triggered the edit
  public EventObject getEditingEvent() {
    return editingEvent;
  }
  // Method invoked when the editor is installed in the table.
  // Overridden in derived classes to take any convenient
  // action.
  public void editingStarted(EventObject event) {
  }
  protected void fireEditingStopped() {
    Object[] l = listeners.getListenerList();
    for (int i = l.length - 2; i >= 0; i -= 2) {
      if (l[i] == CellEditorListener.class) {
        if (changeEvent == null) {
          changeEvent = new ChangeEvent(this);
        }
        ((CellEditorListener) l[i + 1]).editingStopped(changeEvent);
      }
    }
  }
  protected void fireEditingCanceled() {
    Object[] l = listeners.getListenerList();
    for (int i = l.length - 2; i >= 0; i -= 2) {
      if (l[i] == CellEditorListener.class) {
        if (changeEvent == null) {
          changeEvent = new ChangeEvent(this);
        }
        ((CellEditorListener) l[i + 1]).editingCanceled(changeEvent);
      }
    }
  }
  // Implementation of the PropertyChangeListener interface
  public void propertyChange(PropertyChangeEvent evt) {
    if (evt.getPropertyName().equals("ancestor")
        && evt.getNewValue() != null) {
      // Added to table - notify the editor
      editingStarted(editingEvent);
    }
  }
  protected static JCheckBox checkBox = new JCheckBox();
  protected static ChangeEvent changeEvent;
  protected JComponent editor;
  protected EventListenerList listeners = new EventListenerList();
  protected EventObject editingEvent;
}
class TestUpdatableCurrencyTableModel extends UpdatableCurrencyTableModel {
  public void updateTable(Object value, int row, int column) {
    System.out.println("Update for row " + row + " required.");
    System.out.println("Values are " + getValueAt(row, 1) + ", "
        + getValueAt(row, 2) + "; diff is " + getValueAt(row, 3));
  }
}
abstract class UpdatableCurrencyTableModel extends EditableCurrencyTableModel {
  public int getColumnCount() {
    return super.getColumnCount() + 1;
  }
  public Object getValueAt(int row, int column) {
    if (column == BUTTON_COLUMN) {
      return "Update";
    }
    return super.getValueAt(row, column);
  }
  public Class getColumnClass(int column) {
    if (column == BUTTON_COLUMN) {
      return String.class;
    }
    return super.getColumnClass(column);
  }
  public String getColumnName(int column) {
    if (column == BUTTON_COLUMN) {
      return "";
    }
    return super.getColumnName(column);
  }
  public boolean isCellEditable(int row, int column) {
    return column == BUTTON_COLUMN || super.isCellEditable(row, column);
  }
  public void setValueAt(Object value, int row, int column) {
    if (column == BUTTON_COLUMN) {
      // Button press - do whatever is needed to update the table source
      updateTable(value, row, column);
      return;
    }
    // Other columns - use superclass
    super.setValueAt(value, row, column);
  }
  // Used to implement the table update
  protected abstract void updateTable(Object value, int row, int column);
  protected static final int BUTTON_COLUMN = 4;
}
class EditableCurrencyTableModel extends CurrencyTableModel {
  public boolean isCellEditable(int row, int column) {
    return column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN;
  }
  public void setValueAt(Object value, int row, int column) {
    try {
      if (column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN) {
        Double newObjectValue; // New value as an Object
        double newValue; // double, for validity checking
        if (value instanceof Number) {
          // Convert Number to Double
          newValue = ((Number) value).doubleValue();
          newObjectValue = new Double(newValue);
        } else if (value instanceof String) {
          // Convert a String to a Double
          newObjectValue = new Double((String) value);
          newValue = newObjectValue.doubleValue();
        } else {
          // Unrecognized - ignore
          return;
        }
        if (newValue > (double) 0.0) {
          // Store new value, but reject zero or negative values
          data[row][column] = newObjectValue;
          data[row][DIFF_COLUMN] = new Double(
              ((Double) data[row][NEW_RATE_COLUMN]).doubleValue()
                  - ((Double) data[row][OLD_RATE_COLUMN])
                      .doubleValue());
          fireTableRowsUpdated(row, row);
        }
      }
    } catch (NumberFormatException e) {
      // Ignore a badly-formatted number
    }
  }
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))),
          new Double(0.6213051), new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}





Table Row Header Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
/**
 * @version 1.0 11/09/98
 */
class RowHeaderRenderer extends JLabel implements ListCellRenderer {
  RowHeaderRenderer(JTable table) {
    JTableHeader header = table.getTableHeader();
    setOpaque(true);
    setBorder(UIManager.getBorder("TableHeader.cellBorder"));
    setHorizontalAlignment(CENTER);
    setForeground(header.getForeground());
    setBackground(header.getBackground());
    setFont(header.getFont());
  }
  public Component getListCellRendererComponent(JList list, Object value,
      int index, boolean isSelected, boolean cellHasFocus) {
    setText((value == null) ? "" : value.toString());
    return this;
  }
}
public class RowHeaderExample extends JFrame {
  public RowHeaderExample() {
    super("Row Header Example");
    setSize(300, 150);
    ListModel lm = new AbstractListModel() {
      String headers[] = { "a", "b", "c", "d", "e", "f", "g", "h", "i" };
      public int getSize() {
        return headers.length;
      }
      public Object getElementAt(int index) {
        return headers[index];
      }
    };
    DefaultTableModel dm = new DefaultTableModel(lm.getSize(), 10);
    JTable table = new JTable(dm);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    JList rowHeader = new JList(lm);
    rowHeader.setFixedCellWidth(50);
    rowHeader.setFixedCellHeight(table.getRowHeight()
        + table.getRowMargin());
    //                           + table.getIntercellSpacing().height);
    rowHeader.setCellRenderer(new RowHeaderRenderer(table));
    JScrollPane scroll = new JScrollPane(table);
    scroll.setRowHeaderView(rowHeader);
    getContentPane().add(scroll, BorderLayout.CENTER);
  }
  public static void main(String[] args) {
    RowHeaderExample frame = new RowHeaderExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setVisible(true);
  }
}





Table Utilities

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
public class TableUtilities {
  // Calculate the required width of a table column
  public static int calculateColumnWidth(JTable table, 
                  int columnIndex) {
    int width = 0;      // The return value
    int rowCount = table.getRowCount();      
    
    for (int i = 0; i < rowCount ; i++) {
      TableCellRenderer renderer = table.getCellRenderer(i, columnIndex);
      Component comp = renderer.getTableCellRendererComponent(
                table, table.getValueAt(i, columnIndex),
                false, false, i, columnIndex);
      int thisWidth = comp.getPreferredSize().width;
      if (thisWidth > width) {
        width = thisWidth;
      }
    }    
    return width;    
  }
  // Set the widths of every column in a table
  public static void setColumnWidths(JTable table, Insets insets,
                  boolean setMinimum, 
                  boolean setMaximum) {
    int columnCount = table.getColumnCount();
    TableColumnModel tcm = table.getColumnModel();
    int spare = (insets == null ? 0 : insets.left + insets.right);
    
    for (int i = 0; i < columnCount; i++) {
      int width = calculateColumnWidth(table, i);
      width += spare;
      TableColumn column = tcm.getColumn(i);
      column.setPreferredWidth(width);
      if (setMinimum == true) {
        column.setMinWidth(width);
      }
      if (setMaximum == true) {
        column.setMaxWidth(width);
      }
    }
  }
  // Sort an array of integers in place
  public static void sort(int[] values) {
    int length = values.length;
    if (length > 1) {
      for (int i = 0; i < length - 1 ; i++) {
        for (int j = i + 1; j < length; j++) {
          if (values[j] < values[i]) {
            int temp = values[i];
            values[i] = values[j];
            values[j] = temp;
          }
        }
      }
    }
  }
}





ToolTip Header Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */

import java.awt.BorderLayout;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
/**
 * @version 1.0 02/25/99
 */
public class ToolTipHeaderTableExample extends JPanel {
  public ToolTipHeaderTableExample() {
    setLayout(new BorderLayout());
    String[] headerStr = { "default", "jw", "ja", "la", "unknown" };
    String[] toolTipStr = { "", "Javanese", "Japanese", "Latin" };
    DefaultTableModel dm = new DefaultTableModel(headerStr, 4);
    JTable table = new JTable(dm);
    ToolTipHeader header = new ToolTipHeader(table.getColumnModel());
    header.setToolTipStrings(toolTipStr);
    header.setToolTipText("Default ToolTip TEXT");
    table.setTableHeader(header);
    JScrollPane pane = new JScrollPane(table);
    add(pane, BorderLayout.CENTER);
  }
  public static void main(String[] args) {
    JFrame f = new JFrame("ToolTipHeaderTable Example");
    f.getContentPane().add(new ToolTipHeaderTableExample(),
        BorderLayout.CENTER);
    f.setSize(400, 100);
    f.setVisible(true);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
  class ToolTipHeader extends JTableHeader {
    String[] toolTips;
    public ToolTipHeader(TableColumnModel model) {
      super(model);
    }
    public String getToolTipText(MouseEvent e) {
      int col = columnAtPoint(e.getPoint());
      int modelCol = getTable().convertColumnIndexToModel(col);
      String retStr;
      try {
        retStr = toolTips[modelCol];
      } catch (NullPointerException ex) {
        retStr = "";
      } catch (ArrayIndexOutOfBoundsException ex) {
        retStr = "";
      }
      if (retStr.length() < 1) {
        retStr = super.getToolTipText(e);
      }
      return retStr;
    }
    public void setToolTipStrings(String[] toolTips) {
      this.toolTips = toolTips;
    }
  }
}





ToolTip Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.Color;
import java.awt.ruponent;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class ToolTipTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Tool Tip Table");
    JTable tbl = new JTable(new CurrencyTableModel());
    tbl
        .setDefaultRenderer(java.lang.Number.class,
            new ToolTipFractionCellRenderer(10, 3, 6,
                SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tcm.getColumn(1).setPreferredWidth(100);
    tcm.getColumn(1).setMinWidth(100);
    // Add the stripe renderer.
    StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
        Color.white, null, null);
    // Add the custom header renderer
    MultiLineHeaderRenderer headerRenderer = new MultiLineHeaderRenderer(
        SwingConstants.CENTER, SwingConstants.BOTTOM);
    headerRenderer.setBackground(Color.blue);
    headerRenderer.setForeground(Color.white);
    headerRenderer.setFont(new Font("Dialog", Font.BOLD, 12));
    int columns = tableHeaders.length;
    for (int i = 0; i < columns; i++) {
      tcm.getColumn(i).setHeaderRenderer(headerRenderer);
      tcm.getColumn(i).setHeaderValue(tableHeaders[i]);
    }
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
  // Header values. Note the table model provides
  // string column names that are the default header
  // values.
  public static Object[][] tableHeaders = new Object[][] {
      new String[] { "Currency" },
      new String[] { "Yesterday"s", "Rate" },
      new String[] { "Today"s", "Rate" },
      new String[] { "Rate", "Change" } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon) value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}
class MultiLineHeaderRenderer extends JPanel implements TableCellRenderer {
  public MultiLineHeaderRenderer(int horizontalAlignment,
      int verticalAlignment) {
    this.horizontalAlignment = horizontalAlignment;
    this.verticalAlignment = verticalAlignment;
    switch (horizontalAlignment) {
    case SwingConstants.LEFT:
      alignmentX = (float) 0.0;
      break;
    case SwingConstants.CENTER:
      alignmentX = (float) 0.5;
      break;
    case SwingConstants.RIGHT:
      alignmentX = (float) 1.0;
      break;
    default:
      throw new IllegalArgumentException(
          "Illegal horizontal alignment value");
    }
    setBorder(headerBorder);
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    setOpaque(true);
    background = null;
  }
  public void setForeground(Color foreground) {
    this.foreground = foreground;
    super.setForeground(foreground);
  }
  public void setBackground(Color background) {
    this.background = background;
    super.setBackground(background);
  }
  public void setFont(Font font) {
    this.font = font;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    removeAll();
    invalidate();
    if (value == null) {
      // Do nothing if no value
      return this;
    }
    // Set the foreground and background colors
    // from the table header if they are not set
    if (table != null) {
      JTableHeader header = table.getTableHeader();
      if (header != null) {
        if (foreground == null) {
          super.setForeground(header.getForeground());
        }
        if (background == null) {
          super.setBackground(header.getBackground());
        }
      }
    }
    if (verticalAlignment != SwingConstants.TOP) {
      add(Box.createVerticalGlue());
    }
    Object[] values;
    int length;
    if (value instanceof Object[]) {
      // Input is an array - use it
      values = (Object[]) value;
    } else {
      // Not an array - turn it into one
      values = new Object[1];
      values[0] = value;
    }
    length = values.length;
    // Configure each row of the header using
    // a separate JLabel. If a given row is
    // a JComponent, add it directly..
    for (int i = 0; i < length; i++) {
      Object thisRow = values[i];
      if (thisRow instanceof JComponent) {
        add((JComponent) thisRow);
      } else {
        JLabel l = new JLabel();
        setValue(l, thisRow, i);
        add(l);
      }
    }
    if (verticalAlignment != SwingConstants.BOTTOM) {
      add(Box.createVerticalGlue());
    }
    return this;
  }
  // Configures a label for one line of the header.
  // This can be overridden by derived classes
  protected void setValue(JLabel l, Object value, int lineNumber) {
    if (value != null && value instanceof Icon) {
      l.setIcon((Icon) value);
    } else {
      l.setText(value == null ? "" : value.toString());
    }
    l.setHorizontalAlignment(horizontalAlignment);
    l.setAlignmentX(alignmentX);
    l.setOpaque(false);
    l.setForeground(foreground);
    l.setFont(font);
  }
  protected int verticalAlignment;
  protected int horizontalAlignment;
  protected float alignmentX;
  // These attributes may be explicitly set
  // They are defaulted to the colors and attributes
  // of the table header
  protected Color foreground;
  protected Color background;
  // These attributes have fixed defaults
  protected Border headerBorder = UIManager
      .getBorder("TableHeader.cellBorder");
  protected Font font = UIManager.getFont("TableHeader.font");
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class ToolTipFractionCellRenderer extends FractionCellRenderer {
  public ToolTipFractionCellRenderer(int integer, int fraction,
      int maxFraction, int align) {
    super(integer, fraction, align);
    this.maxFraction = maxFraction; // Number of tooltip fraction digits
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    Component comp = super.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(maxFraction);
      formatter.setMinimumFractionDigits(maxFraction);
      ((JComponent) comp).setToolTipText(formatter
          .format(((Number) value).doubleValue()));
    }
    return comp;
  }
  protected int maxFraction;
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}





Total(Calculate) Row Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
 * (swing1.1beta3) swing#960
 */

import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
/**
 * @version 1.0 12/03/98
 */
class DecimalRenderer extends DefaultTableCellRenderer {
  DecimalFormat formatter;
  DecimalRenderer(String pattern) {
    this(new DecimalFormat(pattern));
  }
  DecimalRenderer(DecimalFormat formatter) {
    this.formatter = formatter;
    setHorizontalAlignment(JLabel.RIGHT);
  }
  public void setValue(Object value) {
    setText((value == null) ? "" : formatter.format(((Double) value)
        .doubleValue()));
  }
}
public class TotalRowExample extends JFrame {
  final private int TOTAL_ROW = 3;
  final private int TOTAL_COLUMN = 1;
  TotalRowExample() {
    super("Total Row Example");
    final DecimalFormat formatter = new DecimalFormat("###,##0.00");
    DefaultTableModel dm = new DefaultTableModel() {
      public void setValueAt(Object value, int row, int col) {
        Vector rowVector = (Vector) dataVector.elementAt(row);
        if (col == TOTAL_COLUMN) {
          Double d = null;
          if (value instanceof Double) {
            d = (Double) value;
          } else {
            try {
              d = new Double(((Number) formatter
                  .parse((String) value)).doubleValue());
            } catch (ParseException ex) {
              d = new Double(0.0);
            }
          }
          rowVector.setElementAt(d, col);
        } else {
          rowVector.setElementAt(value, col);
        }
      }
      public boolean isCellEditable(int row, int col) {
        if (row == TOTAL_ROW)
          return false;
        return true;
      }
      public Class getColumnClass(int col) {
        if (col == TOTAL_COLUMN)
          return Number.class;
        return String.class;
      }
    };
    dm.setDataVector(new Object[][] { { "coffee", new Double(0.0) },
        { "tea", new Double(0.0) }, { "cocoa", new Double(0.0) },
        { "total", new Double(0.0) } },
        new Object[] { "Item", "Price" });
    JTable table = new JTable(dm) {
      public void editingStopped(ChangeEvent e) {
        super.editingStopped(e);
        reCalcurate(getModel());
        repaint();
      }
    };
    table.getColumn("Price")
        .setCellRenderer(new DecimalRenderer(formatter));
    JScrollPane scroll = new JScrollPane(table);
    Container content = getContentPane();
    content.add(scroll);
    setSize(300, 120);
    setVisible(true);
  }
  private void reCalcurate(TableModel ml) {
    if (ml == null)
      return;
    double total = 0.0;
    for (int i = 0; i < TOTAL_ROW; i++) {
      total += ((Double) ml.getValueAt(i, TOTAL_COLUMN)).doubleValue();
    }
    ml.setValueAt(new Double(total), TOTAL_ROW, TOTAL_COLUMN);
  }
  public static void main(String[] args) {
    TotalRowExample frame = new TotalRowExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}





Union Data Table Example

 
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */

import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.SwingConstants;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
/**
 * @version 1.0 11/09/98
 */
public class UnionDataExample extends JFrame {
  UnionDataExample() {
    super("UnionData Example");
    setSize(300, 200);
    final String[] headers = { "a", "b", "c", "d" };
    final String[][] data = new String[6][headers.length];
    final AbstractTableModel dmAB = new AbstractTableModel() {
      public int getRowCount() {
        return data.length;
      }
      public int getColumnCount() {
        return headers.length;
      }
      public String getColumnName(int col) {
        return headers[col];
      }
      public Object getValueAt(int row, int col) {
        return data[row][col];
      }
    };
    final int rowCountA = 3;
    DefaultTableModel dmA = new DefaultTableModel(data, headers) {
      public int getRowCount() {
        return rowCountA;
      }
      public Object getValueAt(int row, int col) {
        Vector rowVector = (Vector) dataVector.elementAt(row);
        return rowVector.elementAt(col);
      }
      public void setValueAt(Object value, int row, int col) {
        data[row][col] = (String) value;
        Vector rowVector = (Vector) dataVector.elementAt(row);
        rowVector.setElementAt(value, col);
        TableModelEvent event = new TableModelEvent(this, row, row, col);
        fireTableChanged(event);
        dmAB.fireTableChanged(event);
      }
    };
    DefaultTableModel dmB = new DefaultTableModel(data, headers) {
      public int getRowCount() {
        return rowCountA;
      }
      //public int getRowCount() { return data.length - rowCountA; }
      public Object getValueAt(int row, int col) {
//        Vector rowVector = (Vector) dataVector.elementAt(row
  //          + rowCountA);
        Vector rowVector = (Vector) dataVector.elementAt(2);
  
        return rowVector.elementAt(col);
      }
      public void setValueAt(Object value, int row, int col) {
        int sRow = row + rowCountA;
        data[sRow][col] = (String) value;
        Vector rowVector = (Vector) dataVector.elementAt(sRow);
        rowVector.setElementAt(value, col);
        TableModelEvent event = new TableModelEvent(this, sRow, sRow,
            col);
        fireTableChanged(event);
        dmAB.fireTableChanged(event);
      }
    };
    JScrollPane scrollA = new JScrollPane(new JTable(dmA));
    JScrollPane scrollB = new JScrollPane(new JTable(dmB));
    JScrollPane scrollAB = new JScrollPane(new JTable(dmAB));
    Box box = new Box(BoxLayout.Y_AXIS);
    box.add(new JLabel("Table A"));
    box.add(scrollA);
    box.add(new JSeparator(SwingConstants.VERTICAL));
    box.add(new JLabel("Table B"));
    box.add(scrollB);
    Box boxAB = new Box(BoxLayout.Y_AXIS);
    boxAB.add(new JLabel("Table A + B"));
    boxAB.add(scrollAB);
    Container content = getContentPane();
    content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS));
    content.add(box);
    content.add(new JSeparator(SwingConstants.HORIZONTAL));
    content.add(boxAB);
  }
  public static void main(String[] args) {
    UnionDataExample frame = new UnionDataExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    frame.setVisible(true);
  }
}





Updatable Highlight Currency Table

 
/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.EventObject;
import javax.swing.CellEditor;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class UpdatableHighlightCurrencyTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Updatable Highlighted Currency Table");
    JTable tbl = new JTable(new TestUpdatableCurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tbl.setShowHorizontalLines(false);
    tbl.setIntercellSpacing(new Dimension(1, 0));
    // Add the stripe renderer in the leftmost four columns.
    StripedTableCellRenderer.installInColumn(tbl, 0, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 1, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 2, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 3, Color.lightGray,
        Color.white, null, null);
    // Add the highlight renderer to the difference column.
    // The following comparator makes it highlight
    // cells with negative numeric values.
    Comparator cmp = new Comparator() {
      public boolean shouldHighlight(JTable tbl, Object value, int row,
          int column) {
        if (value instanceof Number) {
          double columnValue = ((Number) value).doubleValue();
          return columnValue < (double) 0.0;
        }
        return false;
      }
    };
    tcm.getColumn(3).setCellRenderer(
        new HighlightRenderer(cmp, null, Color.pink, Color.black,
            Color.pink.darker(), Color.white));
    // Install a button renderer in the last column
    ButtonRenderer buttonRenderer = new ButtonRenderer();
    buttonRenderer.setForeground(Color.blue);
    buttonRenderer.setBackground(Color.lightGray);
    tcm.getColumn(4).setCellRenderer(buttonRenderer);
    // Install a button editor in the last column
    TableCellEditor editor = new ButtonEditor(new JButton());
    tcm.getColumn(4).setCellEditor(editor);
    // Make the rows wide enough to take the buttons
    tbl.setRowHeight(20);
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class TestUpdatableCurrencyTableModel extends UpdatableCurrencyTableModel {
  public void updateTable(Object value, int row, int column) {
    System.out.println("Update for row " + row + " required.");
    System.out.println("Values are " + getValueAt(row, 1) + ", "
        + getValueAt(row, 2) + "; diff is " + getValueAt(row, 3));
  }
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon) value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}
class HighlightRenderer implements TableCellRenderer {
  public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
      Color backColor, Color foreColor, Color highlightBack,
      Color highlightFore) {
    this.cmp = cmp;
    this.targetRenderer = targetRenderer;
    this.backColor = backColor;
    this.foreColor = foreColor;
    this.highlightBack = highlightBack;
    this.highlightFore = highlightFore;
  }
  public Component getTableCellRendererComponent(JTable tbl, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
    }
    Component comp = renderer.getTableCellRendererComponent(tbl, value,
        isSelected, hasFocus, row, column);
    if (isSelected == false && hasFocus == false && value != null) {
      if (cmp.shouldHighlight(tbl, value, row, column)) {
        comp.setForeground(highlightFore);
        comp.setBackground(highlightBack);
      } else {
        comp.setForeground(foreColor);
        comp.setBackground(backColor);
      }
    }
    return comp;
  }
  protected Comparator cmp;
  protected TableCellRenderer targetRenderer;
  protected Color backColor;
  protected Color foreColor;
  protected Color highlightBack;
  protected Color highlightFore;
}
interface Comparator {
  public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
      int column);
}
abstract class UpdatableCurrencyTableModel extends EditableCurrencyTableModel {
  public int getColumnCount() {
    return super.getColumnCount() + 1;
  }
  public Object getValueAt(int row, int column) {
    if (column == BUTTON_COLUMN) {
      return "Update";
    }
    return super.getValueAt(row, column);
  }
  public Class getColumnClass(int column) {
    if (column == BUTTON_COLUMN) {
      return String.class;
    }
    return super.getColumnClass(column);
  }
  public String getColumnName(int column) {
    if (column == BUTTON_COLUMN) {
      return "";
    }
    return super.getColumnName(column);
  }
  public boolean isCellEditable(int row, int column) {
    return column == BUTTON_COLUMN || super.isCellEditable(row, column);
  }
  public void setValueAt(Object value, int row, int column) {
    if (column == BUTTON_COLUMN) {
      // Button press - do whatever is needed to update the table source
      updateTable(value, row, column);
      return;
    }
    // Other columns - use superclass
    super.setValueAt(value, row, column);
  }
  // Used to implement the table update
  protected abstract void updateTable(Object value, int row, int column);
  protected static final int BUTTON_COLUMN = 4;
}
class BasicCellEditor implements CellEditor, PropertyChangeListener {
  public BasicCellEditor() {
    this.editor = null;
  }
  public BasicCellEditor(JComponent editor) {
    this.editor = editor;
    editor.addPropertyChangeListener(this);
  }
  public Object getCellEditorValue() {
    return null;
  }
  public boolean isCellEditable(EventObject evt) {
    editingEvent = evt;
    return true;
  }
  public boolean shouldSelectCell(EventObject evt) {
    return true;
  }
  public boolean stopCellEditing() {
    fireEditingStopped();
    return true;
  }
  public void cancelCellEditing() {
    fireEditingCanceled();
  }
  public void addCellEditorListener(CellEditorListener l) {
    listeners.add(CellEditorListener.class, l);
  }
  public void removeCellEditorListener(CellEditorListener l) {
    listeners.remove(CellEditorListener.class, l);
  }
  // Returns the editing component
  public JComponent getComponent() {
    return editor;
  }
  // Sets the editing component
  public void setComponent(JComponent comp) {
    editor = comp;
  }
  // Returns the event that triggered the edit
  public EventObject getEditingEvent() {
    return editingEvent;
  }
  // Method invoked when the editor is installed in the table.
  // Overridden in derived classes to take any convenient
  // action.
  public void editingStarted(EventObject event) {
  }
  protected void fireEditingStopped() {
    Object[] l = listeners.getListenerList();
    for (int i = l.length - 2; i >= 0; i -= 2) {
      if (l[i] == CellEditorListener.class) {
        if (changeEvent == null) {
          changeEvent = new ChangeEvent(this);
        }
        ((CellEditorListener) l[i + 1]).editingStopped(changeEvent);
      }
    }
  }
  protected void fireEditingCanceled() {
    Object[] l = listeners.getListenerList();
    for (int i = l.length - 2; i >= 0; i -= 2) {
      if (l[i] == CellEditorListener.class) {
        if (changeEvent == null) {
          changeEvent = new ChangeEvent(this);
        }
        ((CellEditorListener) l[i + 1]).editingCanceled(changeEvent);
      }
    }
  }
  // Implementation of the PropertyChangeListener interface
  public void propertyChange(PropertyChangeEvent evt) {
    if (evt.getPropertyName().equals("ancestor")
        && evt.getNewValue() != null) {
      // Added to table - notify the editor
      editingStarted(editingEvent);
    }
  }
  protected static JCheckBox checkBox = new JCheckBox();
  protected static ChangeEvent changeEvent;
  protected JComponent editor;
  protected EventListenerList listeners = new EventListenerList();
  protected EventObject editingEvent;
}
class ButtonEditor extends BasicCellEditor implements ActionListener,
    TableCellEditor {
  public ButtonEditor(JButton button) {
    super(button);
    button.addActionListener(this);
  }
  public void setForeground(Color foreground) {
    this.foreground = foreground;
    editor.setForeground(foreground);
  }
  public void setBackground(Color background) {
    this.background = background;
    editor.setBackground(background);
  }
  public void setFont(Font font) {
    this.font = font;
    editor.setFont(font);
  }
  public Object getCellEditorValue() {
    return value;
  }
  public void editingStarted(EventObject event) {
    // Edit starting - click the button if necessary
    if (!(event instanceof MouseEvent)) {
      // Keyboard event - click the button
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          ((JButton) editor).doClick();
        }
      });
    }
  }
  public Component getTableCellEditorComponent(JTable tbl, Object value,
      boolean isSelected, int row, int column) {
    editor.setForeground(foreground != null ? foreground : tbl
        .getForeground());
    editor.setBackground(background != null ? background : tbl
        .getBackground());
    editor.setFont(font != null ? font : tbl.getFont());
    this.value = value;
    setValue(value);
    return editor;
  }
  protected void setValue(Object value) {
    JButton button = (JButton) editor;
    if (value == null) {
      button.setText("");
      button.setIcon(null);
    } else if (value instanceof Icon) {
      button.setText("");
      button.setIcon((Icon) value);
    } else if (value instanceof DataWithIcon) {
      DataWithIcon d = (DataWithIcon) value;
      button.setText(d.toString());
      button.setIcon(d.getIcon());
    } else {
      button.setText(value.toString());
      button.setIcon(null);
    }
  }
  public void actionPerformed(ActionEvent evt) {
    // Button pressed - stop the edit
    stopCellEditing();
  }
  protected Object value;
  protected Color foreground;
  protected Color background;
  protected Font font;
}
class EditableCurrencyTableModel extends CurrencyTableModel {
  public boolean isCellEditable(int row, int column) {
    return column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN;
  }
  public void setValueAt(Object value, int row, int column) {
    try {
      if (column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN) {
        Double newObjectValue; // New value as an Object
        double newValue; // double, for validity checking
        if (value instanceof Number) {
          // Convert Number to Double
          newValue = ((Number) value).doubleValue();
          newObjectValue = new Double(newValue);
        } else if (value instanceof String) {
          // Convert a String to a Double
          newObjectValue = new Double((String) value);
          newValue = newObjectValue.doubleValue();
        } else {
          // Unrecognized - ignore
          return;
        }
        if (newValue > (double) 0.0) {
          // Store new value, but reject zero or negative values
          data[row][column] = newObjectValue;
          data[row][DIFF_COLUMN] = new Double(
              ((Double) data[row][NEW_RATE_COLUMN]).doubleValue()
                  - ((Double) data[row][OLD_RATE_COLUMN])
                      .doubleValue());
          fireTableRowsUpdated(row, row);
        }
      }
    } catch (NumberFormatException e) {
      // Ignore a badly-formatted number
    }
  }
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class ButtonRenderer extends JButton implements TableCellRenderer {
  public ButtonRenderer() {
    this.border = getBorder();
    this.setOpaque(true);
  }
  public void setForeground(Color foreground) {
    this.foreground = foreground;
    super.setForeground(foreground);
  }
  public void setBackground(Color background) {
    this.background = background;
    super.setBackground(background);
  }
  public void setFont(Font font) {
    this.font = font;
    super.setFont(font);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    Color cellForeground = foreground != null ? foreground : table
        .getForeground();
    Color cellBackground = background != null ? background : table
        .getBackground();
    setFont(font != null ? font : table.getFont());
    if (hasFocus) {
      setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
      if (table.isCellEditable(row, column)) {
        cellForeground = UIManager
            .getColor("Table.focusCellForeground");
        cellBackground = UIManager
            .getColor("Table.focusCellBackground");
      }
    } else {
      setBorder(border);
    }
    super.setForeground(cellForeground);
    super.setBackground(cellBackground);
    // Customize the component"s appearance
    setValue(value);
    return this;
  }
  protected void setValue(Object value) {
    if (value == null) {
      setText("");
      setIcon(null);
    } else if (value instanceof Icon) {
      setText("");
      setIcon((Icon) value);
    } else if (value instanceof DataWithIcon) {
      DataWithIcon d = (DataWithIcon) value;
      setText(d.toString());
      setIcon(d.getIcon());
    } else {
      setText(value.toString());
      setIcon(null);
    }
  }
  protected Color foreground;
  protected Color background;
  protected Font font;
  protected Border border;
}