TITLE:TableCellRendererでセルの背景色を変更
#navi(../)
*TableCellRendererでセルの背景色を変更 [#r8e14fa9]
Posted by [[terai]] at 2004-01-19

#contents

**概要 [#tcf81150]
TableCellRendererを継承するレンダラーを作ってテーブルのセルを修飾します。

-&jnlp;
-&jar;
-&zip;

#screenshot

**サンプルコード [#p4a666c9]
#code{{
public class TestRenderer extends DefaultTableCellRenderer {
  private static final Color ec = new Color(240, 240, 255);
  public TestRenderer() {
    super();
    setOpaque(true);
    setBorder(BorderFactory.createEmptyBorder(0,5,0,5));
  }
  public Component getTableCellRendererComponent(
        JTable table, Object value,
        boolean isSelected, boolean hasFocus,
        int row, int column) {
    super.getTableCellRendererComponent(table, value, 
        isSelected, hasFocus, row, column);
    if(isSelected) {
      setForeground(table.getSelectionForeground());
      setBackground(table.getSelectionBackground());
    }else{
      setForeground(table.getForeground());
      setBackground((row%2==0)?ec:table.getBackground());
    }
    setHorizontalAlignment((value instanceof Number)?RIGHT:LEFT);
    return this;
  }
}
}}

**解説 [#j15250af]
上記のサンプルでは、以下のようなセルレンダラーを作成し、Objectを継承するクラスのデフォルトレンダラーとして設定しています。
-奇数偶数で行の背景色を変更してテーブルをストライプ模様にする
-第0列のカラムのセルを右寄せ
--ここでは、TableColumn#setCellRenderer(TableCellRenderer)((JTable#setDefaultRenderer(Class, TableCellRenderer)でクラスに関連付けるより、各カラムに関連付けした方が優先順位が高い))を使わず、Object.classのDefaultRendererひとつにまとめているため、TableModel#getColumnClass(0)がInteger.classを返すようにしている

#code{{
table.setDefaultRenderer(Object.class, new TestRenderer());
}}

あるセルが描画されるとき、設定されたTableCellRendererのgetTableCellRendererComponentメソッドが呼び出されます。レンダラーは、引数などから得られる情報(選択されているか、何行何列目かなど)を使って、コンポーネントを修飾してからreturnします。

サンプルのTestRendererでは、JLabelを継承するDefaultTableCellRendererを継承しているので、自分自身(this)をsetForeground、setHorizontalAlignmentなどのメソッドで修飾し直し、さらに自分自身(this)を戻り値としています。このようにコンポーネントを使い回しているため、セルの数が膨大になっても、オブジェクトを大量に生成しなくて済むようになっています。

また、返されたコンポーネントは、セルの描画のみに利用されて、コンポーネントとしては機能しません。

セルレンダラーで色を変更する代わりに、以下のようにJTable#prepareRendererメソッドをオーバーライドする方法もあります。使用するセルレンダラーに関係なく、テーブル全体で前処理することができます。このため、Numberクラス用のDefaultTableCellRendererがそのまま使われるので、TableModel#getColumnClass(int)が、Number.classを返すようにしておけば、勝手に右寄せしてくれます。
#code{{
JTable table = new JTable(model) {
  public Component prepareRenderer(TableCellRenderer tcr, int row, int column) {
    Component c = super.prepareRenderer(tcr, row, column);
    if(isRowSelected(row)) {
      c.setForeground(getSelectionForeground());
      c.setBackground(getSelectionBackground());
    }else{
      c.setForeground(getForeground());
      c.setBackground((row%2==0)?evenColor:getBackground());
    }
    return c;
  }
};
}}

**参考リンク [#sdd74788]
-[[Sorting and Otherwise Manipulating Data - How to Use Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)>http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#sorting]]
-[[SwingのJTableコンポーネントでセルを描く>http://www.ibm.com/developerworks/jp/java/library/j-jtable/]]

**コメント [#sfc984fe]
- JTable#prepareRendererメソッドを使用する場合のサンプルを修正。 -- [[terai]] &new{2007-04-04 (水) 19:41:37};
- メモ:[[JTable でセルのないところに行っぽい表示を出せますか? - KrdLabの不定期日記>http://d.hatena.ne.jp/KrdLab/20071209/1197143960]]。これおもしろいです。 -- [[terai]] &new{2007-12-10 (月) 17:25:47};
- ↑ありがとうございます.terai様のサイトは情報が充実していてすばらしいです.参考にさせていただきます. -- [[KrdLab]] &new{2008-01-27 (日) 14:27:53};

#comment