CodeZine(コードジン)

特集ページ一覧

Swing再入門 レンダラーとモデル

第3回 画面表示やデータ管理をカスタマイズする

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2007/09/24 14:00

Swingのコンポーネントの中には「レンダラー」や「モデル」と呼ばれるオブジェクトを使って画面の表示やデータ管理をしているものがあります。これらをカスタマイズしてみましょう。

目次

はじめに

 今回は、各種の情報を保持して利用するコンポーネントについて考えてみます。コンポーネントの中には、さまざまな情報を表示するためのものがあります。比較的単純なものとしてはJComboBoxやJList、複雑なデータ構造を持つものとしてはJTreeやJTableなどがあります。これらは「セル」と呼ばれる、保持している値を表示するための部品を組み合わせて構成されています。

 これらのコンポーネントは、実は1つのクラスだけでできているのではありません。コンポーネントの表示は「レンダラー」と呼ばれるオブジェクトが行い、保持するデータの管理は「モデル」というオブジェクトが行っています。このようにいくつかのオブジェクトによってコンポーネントは構成されているのです。

 ここでは、JListを例に、レンダラーとモデルについて考えてみましょう。

対象読者

  • Javaの基本機能は一通り覚えた、というビギナーを卒業しかけている人。
  • Swingはマスターした? といわれると、ちょっと自信がない人。
  • これからはクライアントサイドが注目されると信じる人。

ListCellRendererとリスト表示コンポーネント

 レンダラーは、「セル」の表示を行うのに用いられるクラスです。これはコンポーネントの種類に応じて複数のものが用意されています。コンポーネントによっては、さまざまな状況に応じて表示が変化したりするので、それらに対応したレンダラーが複数用意されています。

 ここでは、比較的構造のシンプルな「JList」を使ってレンダラーの基本的な使い方を説明しましょう。JListは、コンポーネントの中にいくつかの項目が一覧表示されます。この1つ1つの項目が「セル」なのです。JListでは、セルの表示はjavax.swing.DefaultListCellRendererクラスがレンダラーとして組み込まれています。このDefaultListCellRendererは、javax.swing.ListCellRendererというインターフェイスをimplementsして定義されています。JListのレンダラーは、このListCellRendererをimplementsしたクラスとして定義する必要があります。

 ListCellRendererは、1つのメソッドだけ用意されている非常にシンプルなインターフェイスです。これは次のように定義されています。

public interface ListCellRenderer {

    public Component getListCellRendererComponent(
        JList list,Object object,int index,boolean isSelected,
        boolean hasFocus);
}

 getListCellRendererComponentというメソッドが、レンダラーオブジェクトを作成し返す働きをするものです。このメソッドでは、引数に渡された情報を元に、セルに表示するComponentを作成して返します。要するにレンダラーの正体とは、「必要に応じてセルに表示するComponentを作成して返すもの」だったのです。

 メソッドで渡される引数には、次のような値が収められています。これらの値を元にComponentを作成するわけです。

メソッドに渡される引き数の種類
引数説明
JList listレンダラーを要求してきたJList
Object objectレンダラーを表示するセルの値オブジェクト
int indexセルのインデックス番号
boolean isSelected選択されているか否か
boolean hasFocusフォーカスがあるか否か

 セルに表示される値は、Objectである点に注意しましょう。Stringではありません。JListでは、値はStringである必要はないのです。

色の値を視覚的に表示するレンダラー

 では、実際に簡単なJList用レンダラーを作成してみましょう。ここでは、テキスト以外のオブジェクトを値に保管し表示する例として、Colorの値を視覚的に表示するレンダラークラスを作成してみましょう。

package jp.codezine;

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

public class SampleApp extends JFrame {
    private static final long serialVersionUID = 1L;
    JLabel label;
    JList list;
    
    public SampleApp(){
        this.setSize(new Dimension(250,250));
        label = new JLabel("JList Sample");
        this.add(label,BorderLayout.NORTH);
        list = this.createList();
        this.add(new JScrollPane(list),BorderLayout.CENTER);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    // JListの生成
    public JList createList(){
        MyColor[] array = {new MyColor(255,255,255),
                new MyColor(255,0,0),
                new MyColor(0,255,0),
                new MyColor(0,0,255),
                new MyColor(255,255,0),
                new MyColor(0,255,255),
                new MyColor(255,0,255),
                new MyColor(0,0,0)};
        JList list = new JList(array);
        // ColorRendererをレンダラーに設定する
        list.setCellRenderer(new ColorRenderer());
        return list;
    }

    public static void main(String[] args) {
        new SampleApp().setVisible(true);
    }
}

class ColorRenderer implements ListCellRenderer {

    @Override
    public Component getListCellRendererComponent(JList list,
            Object object, int index, boolean isSelected,
            boolean hasFocus) {
        JLabel label = new JLabel();
        try {
            Color c = (Color)object;
            label.setText(c.toString());
            label.setOpaque(true);
            label.setFont(new Font("Serif",Font.BOLD,16));
            label.setBackground(c);
            int n = c.getRed() + c.getGreen() + c.getBlue();
            // 選択されているかどうかで処理を分ける
            if (isSelected){
                label.setForeground(c);
            } else {
                label.setForeground(n > 384 ?
                    Color.BLACK : Color.WHITE);
            }
        } catch (ClassCastException e) {
            e.printStackTrace();
        }
        return label;
    }
}

class MyColor extends Color {
    private static final long serialVersionUID = 1L;

    public MyColor(int r,int g,int b) {
        super(r, g, b);
    }
    
    @Override
    public String toString() {
        return "[" + this.getRed() +
                ":" + this.getGreen() + ":" + this.getBlue() + "]";
    }
}
色の値を管理するJList。クリックすると選択されたセルのテキストが消える。
色の値を管理するJList。クリックすると選択されたセルのテキストが消える。

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 掌田 津耶乃(ショウダ ツヤノ)

    三文ライター&三流プログラマ。主にビギナーに向けたプログラミング関連の執筆を中心に活動している。 ※現在、入門ドキュメントサイト「libro」、カード型学習サイト「CARD.tuyano.com」を公開中。またGoogle+プロフィールはこちら。

バックナンバー

連載:Swing再入門
All contents copyright © 2005-2020 Shoeisha Co., Ltd. All rights reserved. ver.1.5