TITLE:TableCellRendererでセルの背景色を変更

Posted by aterai at 2004-01-19

TableCellRendererでセルの背景色を変更

TableCellRendererを継承するレンダラーを作ってテーブルのセルを修飾します。

  • &jnlp;
  • &jar;
  • &zip;
StripeTable.png

サンプルコード

class StripeTableRenderer extends DefaultTableCellRenderer {
  private static final Color evenColor = new Color(240, 240, 255);
  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)?evenColor:table.getBackground());
    }
    setHorizontalAlignment((value instanceof Number)?RIGHT:LEFT);
    return this;
  }
}

解説

上記のサンプルでは、以下のようなセルレンダラーを作成し、Objectを継承するクラスのデフォルトレンダラーとして設定しています。

  • 奇数偶数で行の背景色を変更してテーブルをストライプ模様にする
  • 第0列のカラムのセルを右寄せ
    • ここでは、TableColumn#setCellRenderer(TableCellRenderer)*1を使わず、Object.classのDefaultRendererひとつにまとめているため、TableModel#getColumnClass(0)がInteger.classを返すようにしている
table.setDefaultRenderer(Object.class, new StripeTableRenderer());

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

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

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


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

JTable table = new JTable(model) {
  private final Color evenColor = new Color(240, 240, 255);
  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;
  }
};

Java6u10 以降なら、以下のように設定する方法もあります。

  • 注:デフォルトのBoolean用レンダラーの背景色が変わらないようです。
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.table.*;
    class TableAlternateRowColorTest {
      public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
          @Override public void run() {
            createAndShowGUI();
          }
        });
      }
      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);
      }
    }
    

参考リンク

コメント