SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Swing再入門

Swing再入門 コンポーネントの表示方法のカスタマイズ

第2回 コンポーネントの表示を考える

コンポーネントの表示テキスト、マルチフォントにできますか?

 コンポーネントの多くは、コンポーネント上にテキストを表示しています。JLabelJButtonJCheckBoxなど、みんなそうです。この表示テキストは、フォントや色などを変更することができます。では、「テキストをマルチフォントで表示させたい」という場合、どうすればよいでしょうか?

 答えは、実はとても単純です。HTMLで表示テキストを作成し、設定すれば良いのです。Swingのコンポーネントは、HTMLをレンダリングして表示させることができます。これを利用すれば、思った以上に凝ったテキスト表示を行わせることができます。

 例えば、先ほどのSampleAppのコンストラクタを次のように変更してみましょう。ボタンに黒と赤でテキストが表示されるはずです。

public SampleApp(){
    this.setSize(new Dimension(200,200));
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    BoxLayout boxlayout =
        new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS);
    this.setLayout(boxlayout);
    for(int i = 0;i < 3;i++){
        JButton btn = new JButton(
            "<html><b>Button<span style=\"color:#FF0000;\">"
            + i + "</span></b></html>");
        btn.setFont(new Font("Serif",Font.PLAIN,18));
        
        this.add(btn);
    }
}
黒字のボタン名に赤い番号が表示される。HTMLを使えば簡単にマルチフォント表示ができる。
黒字のボタン名に赤い番号が表示される。HTMLを使えば簡単にマルチフォント表示ができる。

 表示テキストに"<html>~テキスト~</html>"というようにして開始部分と終了部分に<html>、</html>をつけておけば、そのテキストをHTMLのコードとして認識します。

 これを利用すれば、例えばボタンに複数行のテキストを表示させたりといったことも簡単に行うことができます。覚えておいて損はないテクニックです。

ルックアンドフィール、変えられますか?

 Swingのコンポーネントの特徴として、「ルックアンドフィールが変更できる」という点が挙げられるでしょう。標準でいくつかのルックアンドフィールを用意しており、簡単な操作でコンポーネントの表示を変更することが可能です。――では、どうやって? 案外、実際にやってみたことない人、多いんじゃないでしょうか。

 せっかくルックアンドフィールを操作できるのですから、そのやり方ぐらいは知っておきたいものです。では、いくつかのコンポーネントを配置した簡単なサンプルを作成してみましょう。

package jp.codezine;

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;

public class SampleApp extends JFrame
        implements ActionListener {
    private static final long serialVersionUID = 1L;
    private LaFComboBox combo;
    
    public SampleApp(){
        this.setSize(new Dimension(200,150));
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridLayout layout = new GridLayout(4,1);
        layout.setHgap(5);
        layout.setVgap(5);
        this.setLayout(layout);
        
        createComponent();
    }
    
    public void createComponent(){
        JCheckBox check = new JCheckBox("checkbox");
        this.add(check);
        JRadioButton radio = new JRadioButton("radio");
        this.add(radio);
        combo = new LaFComboBox();
        combo.addActionListener(this);
        this.add(combo);
        JButton btn = new JButton("button");
        this.add(btn);
    }
    
    public void changeLookAndFeel(){
        String s = combo.getSelectedLaF();
        try {
            UIManager.setLookAndFeel(s);
            SwingUtilities.updateComponentTreeUI(this);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
    }
    
    public void actionPerformed(ActionEvent ev){
        this.changeLookAndFeel();
    }

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

class LaFComboBox extends JComboBox {
    private static final long serialVersionUID = 1L;
    private Map<String,String> map;
    
    public LaFComboBox(){
        UIManager.LookAndFeelInfo[] LaF =
            UIManager.getInstalledLookAndFeels();
        map = new HashMap<String,String>();
        for(UIManager.LookAndFeelInfo lf:LaF){
            this.addItem(lf.getName());
            map.put(lf.getName(),lf.getClassName());
        }
    }
    
    public String getSelectedLaF(){
        String s = (String)this.getSelectedItem();
        return map.get(s);
    }
}
コンポーネントをいくつか組み込んだサンプル。コンボボックスを選ぶとルックアンドフィールが変わる。初期状態では、Metalになっている。
コンポーネントをいくつか組み込んだサンプル。コンボボックスを選ぶとルックアンドフィールが変わる。初期状態では、Metalになっている。
Windowsルックアンドフィール。これはVistaでの表示。
Windowsルックアンドフィール。これはVistaでの表示。
Windowsのクラシック・ルックアンドフィール。
Windowsのクラシック・ルックアンドフィール。
CDE/Motifのルックアンドフィール。
CDE/Motifのルックアンドフィール。

 ここでは、チェックボックス、ラジオボタン、コンボボックス、プッシュボタンといったコンポーネントを配置したウインドウを表示させています。コンボボックスからルックアンドフィール名を選択すると、ウインドウのルックアンドフィールが変更されます。コンボボックスには、利用可能なルックアンドフィール名が表示されているはずです。

ルックアンドフィール操作の仕組み

 ここでは、ルックアンドフィールを表示したコンポーネントとして、JComboBoxを継承した「LaFComboBox」というクラスを用意しました。ここでルックアンドフィール名を表示したコンボボックスを作成しています。また、ルックアンドフィール名とそのクラス名をHashMapに保管し、それを利用して選択したルックアンドフィールのクラス名を取得するためのメソッドも用意しておきました。

 ルックアンドフィールは、文字通りLookAndFeelというクラスとして用意されています。また、ルックアンドフィールに関する情報を管理するものとして、UIManager.LookAndFeelInfoというクラスも用意されています。このクラスを利用して、ルックアンドフィール名やLookAndFeelクラス名などを取得することができます。

 LaFComboBoxのコンストラクタでは、次のようにしてルックアンドフィールに関する情報を取得しています。

UIManager.LookAndFeelInfo[] LaF = UIManager.getInstalledLookAndFeels();

 UIManagerは、文字通りユーザーインターフェイスに関する各種情報を提供する機能を持つクラスです。getInstalledLookAndFeelsは、現在利用可能なルックアンドフィールに関する情報を得るためのメソッドで、UIManager.LookAndFeelInfo配列としてすべてのルックアンドフィールに関する情報を返します。

 このUIManager.LookAndFeelInfoでは、getNamegetClassNameメソッドにより、ルックアンドフィール名やクラス名を得ることができます。ここでは、あらかじめHashMapを用意しておき、そこにgetName値をキーにしてgetClassName値を保存しておきました。こうすることで、コンボボックスで選択した名前のキーの値を調べればクラス名が分かるようにしておいたわけです。

 Swingでは、LookAndFeelクラスを直接利用してルックアンドフィールを変更することもできますし、クラス名を使って指定することも可能です。一般に、扱いやすいクラス名のString値を用意して操作することが多いでしょう。ここでもそうしています。ActionListenerで実行しているactionPerformedを見ると、getSelectedLaFでクラス名を取り出し、それを使ってルックアンドフィールを変更しています。

UIManager.setLookAndFeel(s);

 引数にStringを指定するsetLookAndFeelメソッドは、ClassNotFoundExceptionInstantiationExceptionIllegalAccessExceptionUnsupportedLookAndFeelExceptionとさまざまな例外を発生させる場合があるので注意が必要です。

 これでルックアンドフィールは設定されましたが、この状態ではまだ各コンポーネントのルックアンドフィールは変更されません。このsetLookAndFeelで設定されるのは「デフォルトのルックアンドフィール」です。すなわち、これ以後コンポーネントを新たに作成すると、指定したルックアンドフィールで作成される、ということなのです。

 コンポーネント類は、それまで設定されていたルックアンドフィールを使って既に表示が作成済みです。従って、作成したコンポーネントのルックアンドフィールを新たに設定したものに更新しなければいけません。

SwingUtilities.updateComponentTreeUI(this);

 これが、その作業を行っているところです。コンポーネントは、大元となるコンテナ(通常はJFrame)内にツリー構造で組み込まれています。そのツリー構造に従って、組み込まれているコンポーネントのルックアンドフィールをすべて更新していきます。引数にJFrameを渡せば、そのJFrame内に組み込まれているコンポーネント類すべてが現在のルックアンドフィールに変わるわけです。

次のページ
Metalを自由に変更できますか?

この記事は参考になりましたか?

Swing再入門連載記事一覧

もっと読む

この記事の著者

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

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/1640 2007/09/05 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー