ListCellRenderer(項目の表示方法を操作する)

広告

JListクラスのメソッドを使って、選択項目の前景色や背景色を指定したり、幅や高さを指定したりといったことができましたが、もう少し自由に表示方法を制御したい場合にはListCellRendererインターフェースを使います。

ListCellRendererインターフェースで実装が必要なメソッドは"getListCellRendererComponent"メソッドだけです。

指定された値を表示するように設定されたコンポーネントを返します。次に、
そのコンポーネントの paint メソッドが呼び出されて、セルを「描画」しま
す。リストセルのサイズが固定されていないため、リストの寸法を計算する
必要がある場合には、このメソッドが呼び出されて、getPreferredSize を呼
び出せるコンポーネントを生成します。

パラメータ:
  list - ペイントしている JList
  value - list.getModel().getElementAt(index) によって返される値
  index - セルのインデックス
  isSelected - 指定されたセルが選択された場合は true
  cellHasFocus - 指定されたセルにフォーカスがある場合は true 
戻り値:
  指定された値を描画する paint() メソッドがあるコンポーネント

このメソッドは、リストの各項目が表示されようとした時に、上記メソッド内に記述された方法で項目を描画します。

実際に描画されるものは、このメソッドの戻り値となります。自分で項目の値を加工して戻り値として戻してもいいですし、全然関係無い処理を行って戻り値として戻しても構いません。

ListCellRendererインターフェースの実装サンプルとしてJDKのAPI解説のところに下記のようなサンプルが書いてあります。

class MyCellRenderer extends JLabel implements ListCellRenderer {
  public MyCellRenderer() {
    setOpaque(true);
  }

  public Component getListCellRendererComponent(
    JList list,
    Object value,
    int index,
    boolean isSelected,
    boolean cellHasFocus){

    setText(value.toString());
    setBackground(isSelected ? Color.red : Color.white);
    setForeground(isSelected ? Color.white : Color.black);

    return this;
  }
}

このサンプルでは、リストの各項目を表示する際に、その項目が選択状態にある時は"赤色"で、そうでない時は"白色"で表示するように指定しています。

また戻値としては"this"を返していますので自分自身を返すことになるのですが、このクラスは"JLabel"を継承しているため、実際にはJLabelのオブジェクトが戻値として帰っています。つまり、リストの各項目はJLabelのオブジェクトが表示されていて、状態によって赤色であったり白色であったりすることになります。

ちなみに"getListCellRendererComponent"メソッドの引数の値ですが、"value"にはリストの項目データが渡されてきます。今までのサンプルですと、リストのデータには"String"クラスの値を使っていましたので、このような場合には"value"にはStringクラスのオブジェクトが渡されてきます。

先ほどのサンプルでは、渡された来た"value"の値から文字列の値を取り出しています。

次にListCellRendererインターフェースを実装したクラスを作成したら、JListに対して、このCellRendererクラスのオブジェクトを使うことを設定してあげる必要があります。設定するにはJListクラスの"setCellRenderer"メソッドを使います。

リスト内の各セルを描画する委譲を設定します。prototypeCellValue が設定
されていれば、fixedCellWidth および fixedCellHeight プロパティも設定さ
れます。しかし、cellRenderer プロパティに対しては PropertyChangeEvent 
は 1 つだけ生成されます。 

このプロパティのデフォルト値は ListUI 委譲 (Look & Feel の実装) によって提供
されます。

パラメータ:
  cellRenderer - リスト内のセルを描画する ListCellRenderer

では実際にサンプルを作ってみます。下記では選択された項目を●で囲って表示するようにしています。

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

public class JListSample extends JFrame{

  public static void main(String[] args){
    JListSample test = new JListSample("JListSample");

    /* 終了処理を変更 */
    test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    test.setBounds( 10, 10, 250, 130);
    test.setVisible(true);
  }

  JListSample(String title){
    setTitle(title);

    /* JListの初期データ */
    String[] initData = {"Blue", "Green", "Red", "Whit", "Black"};
    JList list = new JList(initData);

    /* CellRendererを設定する */
    MyCellRenderer renderer = new MyCellRenderer();
    list.setCellRenderer(renderer);

    JScrollPane sp = new JScrollPane();
    sp.getViewport().setView(list);
    sp.setPreferredSize(new Dimension(200, 80));

    JPanel p = new JPanel();
    p.add(sp);

    getContentPane().add(p, BorderLayout.CENTER);
  }

  class MyCellRenderer implements ListCellRenderer {
    JLabel label;

    public MyCellRenderer() {
      label = new JLabel();
      label.setOpaque(true);
    }

    public Component getListCellRendererComponent(
      JList list,
      Object value,
      int index,
      boolean isSelected,
      boolean cellHasFocus){

      if (isSelected){
        label.setText("●  " + value.toString() + "  ●");

        label.setBackground(Color.red);
        label.setForeground(Color.white);
      }else{
        label.setText(value.toString());

        label.setBackground(Color.white);
        label.setForeground(Color.black);
      }

      return label;
    }
  }
}

実行結果は下記のようになります。

ListCellRenderer(項目の表示方法を操作する)

ListCellRenderer(項目の表示方法を操作する)

このページではリストの項目としてJLabelを使っていましたが、次のページではJLabelクラス以外の値を使った場合にどうなるかを試してみます。

( Written by Tatsuo Ikura )

関連記事 (一部広告含む)