• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:TableCellRendererでセルの背景色を変更
#navi(../)
RIGHT:Posted by [[terai]] at 2004-01-19
*TableCellRendererでセルの背景色を変更 [#r8e14fa9]
TableCellRendererを継承するレンダラーを作ってテーブルのセルを修飾します。
---
category: swing
folder: StripeTable
title: TableCellRendererでセルの背景色を変更
tags: [JTable, TableCellRenderer, UIManager]
author: aterai
pubdate: 2004-01-19
description: TableCellRendererを継承するレンダラーを作ってテーブルのセルを修飾します。
image: https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTT1bwXoBI/AAAAAAAAAlE/jmpoFwDpvqs/s800/StripeTable.png
---
* 概要 [#summary]
`TableCellRenderer`を継承するレンダラーを作ってテーブルのセルを修飾します。

-&jnlp;
-&jar;
-&zip;
#download(https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTT1bwXoBI/AAAAAAAAAlE/jmpoFwDpvqs/s800/StripeTable.png)

#screenshot

**サンプルコード [#p4a666c9]
#code{{
* サンプルコード [#sourcecode]
#code(link){{
class StripeTableRenderer extends DefaultTableCellRenderer {
  private static final Color evenColor = new Color(240, 240, 255);
  public Component getTableCellRendererComponent(JTable table, Object value,
  @Override 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) {
    if (isSelected) {
      setForeground(table.getSelectionForeground());
      setBackground(table.getSelectionBackground());
    }else{
    } else {
      setForeground(table.getForeground());
      setBackground((row%2==0)?evenColor:table.getBackground());
      setBackground((row % 2 == 0) ? evenColor : table.getBackground());
    }
    setHorizontalAlignment((value instanceof Number)?RIGHT:LEFT);
    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を返すようにしている
* 解説 [#explanation]
上記のサンプルでは、以下のようなセルレンダラーを作成し、`Object`を継承するクラスのデフォルトレンダラーとして設定しています。

- 奇数偶数で行の背景色を変更してテーブルをストライプ模様にする
- 第`0`列のカラムのセルを右寄せ
-- ここでは`TableColumn#setCellRenderer(TableCellRenderer)`を使用せずに`Object.classのDefaultRenderer`ひとつにまとめているため、`TableModel#getColumnClass(0)`が`Integer.class`を返すよう設定
-- `JTable#setDefaultRenderer(Class, TableCellRenderer)`でクラスに関連付けるより、各カラムに関連付けした方が優先順位が高い

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

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

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

また、返されたコンポーネントは、セルの描画のみに利用されて、コンポーネントとしては機能しません。
また返されたコンポーネントはセルの描画のためだけに利用されマウスイベントなどは無視されます。

----
セルレンダラーで色を変更する代わりに、以下のようにJTable#prepareRendererメソッドをオーバーライドする方法もあります。使用するセルレンダラーに関係なく、テーブル全体で前処理することができます。このため、Numberクラス用のDefaultTableCellRendererがそのまま使われるので、TableModel#getColumnClass(int)が、Number.classを返すようにしておけば、勝手に右寄せしてくれます。
セルレンダラーで色を変更する代わりに以下のように`JTable#prepareRenderer`メソッドをオーバーライドする方法もあります。この場合使用するセルレンダラーに関係なくテーブル全体での前処理が可能です。このため`Number`クラス用デフォルトレンダラーの`JTable$NumberRenderer`がそのまま使用され、`TableModel#getColumnClass(int)`が`Number.class`を返すようにしておけば自動的に右寄せになります。

#code{{
JTable table = new JTable(model) {
  private final Color evenColor = new Color(240, 240, 255);
  public Component prepareRenderer(TableCellRenderer tcr, int row, int column) {
  @Override public Component prepareRenderer(TableCellRenderer tcr, int row, int column) {
    Component c = super.prepareRenderer(tcr, row, column);
    if(isRowSelected(row)) {
    if (isRowSelected(row)) {
      c.setForeground(getSelectionForeground());
      c.setBackground(getSelectionBackground());
    }else{
    } else {
      c.setForeground(getForeground());
      c.setBackground((row%2==0)?evenColor:getBackground());
      c.setBackground((row % 2 == 0) ? evenColor : getBackground());
    }
    return c;
  }
};
}}

----
Java6u10なら、以下のように設定する方法もあるようです。
-[[java.net Forums : JTable-Zebra with one line ... ...>http://forums.java.net/jive/thread.jspa?messageID=338905]]
`JDK 1.6.0_10`以降では、以下のように設定する方法もあります。

- [http://forums.java.net/jive/thread.jspa?messageID=338905 java.net Forums : JTable-Zebra with one line ... ...]

#code{{
UIManager.put("Table.alternateRowColor", Color.PINK);
}}
--デフォルトのBooleanレンダラーはうまくいかない

- 注: デフォルトの`Boolean`用レンダラーの背景色は変更されない

#code{{
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
class MainPanel {
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
public class TableAlternateRowColorTest {
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      UIManager.put("Table.alternateRowColor", Color.ORANGE);
      String[] columnNames = {"String", "Integer", "Boolean"};
      Object[][] data = {
        {"A", 1, true}, {"B", 2, false}, {"C", 0, true}
      };
      TableModel model = new DefaultTableModel(data, columnNames) {
        @Override public Class<?> getColumnClass(int column) {
          return getValueAt(0, column).getClass();
        }
      };
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new JScrollPane(new JTable(model)));
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
  public static void createAndShowGUI() {
    UIManager.put("Table.alternateRowColor", Color.ORANGE);
    String[] columnNames = {"String", "Integer", "Boolean"};
    Object[][] data = { {"AAA", 1, true}, {"BBB", 2, false} };
    DefaultTableModel model = new DefaultTableModel(data, columnNames) {
      @Override
      public Class<?> getColumnClass(int column) {
        return getValueAt(0, column).getClass();
      }
    };
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new JScrollPane(new JTable(model)));
    frame.setSize(320, 240);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
}}

**参考リンク [#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/]]
* 参考リンク [#reference]
- [https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#sorting Sorting and Otherwise Manipulating Data - How to Use Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)]
- [https://www.ibm.com/developerworks/jp/java/library/j-jtable/ Swingの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]
#comment
- `JTable#prepareRenderer`メソッドを使用する場合のサンプルを修正。 -- &user(aterai); &new{2007-04-04 (水) 19:41:37};
- メモ: [http://d.hatena.ne.jp/KrdLab/20071209/1197143960 JTable でセルのないところに行っぽい表示を出せますか? - KrdLabの不定期日記]。これおもしろいです。 -- &user(aterai); &new{2007-12-10 (月) 17:25:47};
- ↑ありがとうございます.terai様のサイトは情報が充実していてすばらしいです.参考にさせていただきます. -- &user(KrdLab); &new{2008-01-27 (日) 14:27:53};

#comment