Bits of Java (トップ)

VM   JDK と JRE
Language   オブジェクトとインスタンス   this と super   static   フィールドアクセス
IO   Serializable の実装
Swing   MetalLookAndFeel   イメージパネル
JavaBeans   プロパティ名について   XMLEncoder で保存
その他   正規表現テストアプリ   秀丸の強調表示   Ant のインストール   文字セット変換 Ant タスク   XAMPP + Tomcat

MetalLookAndFeel の フォントスタイルについて

Swing で作成したアプリケーションを MetalLookAndFeel で表示するといくつかのコンポーネントで BOLD フォントを使用している為に日本語があまりきれいではない場合がありますが、これは MetalLookAndFeel が使用するデフォルトのメタルテーマ (javax.swing.plaf.metal.DefaultMetalTheme) の設定が反映されている為です。

下は WindowsXP、 J2SE1.4.2_06 で J2SDKEE1.3.1 の配備ツールを起動した際のウィンドウです。
デフォルトの MetalLookAndFeel で表示されています。

ボールド表示されている日本語が少しつぶれた感じです。 フレームのタイトルもボールドですがこちらは JAVA ではなく OS が作成しているようです。 一番簡単な対処法ですが JAVA_HOME/jre/lib/swing.properties ファイルにデフォルトのルックアンドフィールを設定することができるので MetalLookAndFeel 以外を使用するように設定します。
以降 特に記述しませんが SDK (JDK) をインストールの際に JRE 環境もインストールしている場合には JRE_HOME/lib/swing.properties も同様に設定してください。

WindowsXP にインストールした J2SE 1.4.2 (以下 JDK1.5 でも同様に適用できる内容です) にはデフォルトでは swing.properties ファイルはありませんでした。
その場合には下の1行のみが内容の
swing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel
JAVA_HOME/jre/lib/swing.properties ファイルを作成してください。
もし swing.properties ファイルがすでに存在する場合にはその内容に swing.defaultlaf プロパティの設定があれば com.sun.java.swing.plaf.windows.WindowsLookAndFeel を値として記述し、もし swing.defaultlaf プロパティの設定がなければ

    swing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel
という行を最初の行にでも挿入してください。
swing.defaultlaf プロパティに既に他の ルックアンドフィールが設定されている場合には必要に応じて変更してください。
先ほどの J2EE の配備ツールの場合はウィンドウズルックアンドフィールでは 下のようなウィンドウになります。 (このウィンドウは WindowsXP の設定が反映されています)

以下のコードで使用可能なルックアンドフィールが分かります。

    javax.swing.UIManager.LookAndFeelInfo[] infos =
                      javax.swing.UIManager.getInstalledLookAndFeels();
    for (int i = 0; i < infos.length; i++) {
        System.out.println(infos[i].getName() + "   " + infos[i].getClassName());
    }
OS が Windows 以外の場合でもモチーフルックアンドフィールは使えると思います。
Windows の場合と同様に swing.properties ファイルに
    swing.defaultlaf=com.sun.java.swing.plaf.motif.MotifLookAndFeel
を設定すると下のようなウィンドウになります。


J2SE 5.0 (JDK1.5.0) から MetalLookAndFeel のデフォルトのメタルテーマが Steel (javax.swing.plaf.metal.DefaultMetalTheme) から Ocean (javax.swing.plaf.metal.OceanTheme) に変更されました。 また Windows においては劇的と言えるくらいデフォルトで表示した際の BOLD フォントの表示がきれいになりました。 きっと尽力なされた方がいらっしゃるのでしょう (感謝)。 下は WindowsXP, JDK1.5.0, MetalLookAndFeel の場合のウィンドウです。

フォントを BOLD から PLAIN に変更すると下のようになります。

メタルテーマの変更以外にも JDK1.5 からは MetalLookAndFeel のすべてのコンポーネントにおいてデフォルトで PLAIN フォントを使用するように変更できる swing.boldMetal というシステムプロパティがサポートされるようになりました。
アプリケーションのユーザとしてはオプション -D を使って 以下のように起動することで PLAIN フォントに変更できます。

    java -Dswing.boldMetal=false MyApp
起動時のオプション -D で設定することもありドキュメントにもシステムプロパティと書いてありましたが
    System.getProperty("swing.boldMetal");
としても設定に関わらず常に null が返されます。 UIManager を通して UIDefaults に設定されるので UI プロパティと呼んだ方が分かりやすいかもしれません。

なお変更されるのはあくまでもデフォルトのフォントスタイルでプログラムにおいてコンポーネントの setFont メソッドでフォントを設定している場合には swing.boldMetal の設定に関わらず setFont メソッドで設定されたフォントのスタイルが常に有効になります。

アプレットの場合は "Java コントロールパネル" (Windows の場合はコントロールパネルの "Java" をクリックすると表示されます) で設定できます。 "Java" タブの "Java アプレットのランタイム設定" の "表示" ボタンをクリックすると "Java ランタイム設定" というウィンドウが表示されるのでその "Java ランタイムパラメータ" に下の1行を設定してから両ウィンドウの "了解" ボタンを押します。

    -Dswing.boldMetal=false

プログラムにおいては main メソッドなどで最初の Swing コンポーネントを作成するコードの前に

    UIManager.put("swing.boldMetal", Boolean.FALSE);
を記述することで MetalLookAndFeel のすべてのコンポーネントのデフォルトフォントスタイルが PLAIN フォントに変更されます。

すでに MetalLookAndFeel でコンポーネントが表示されている場合には

    UIManager.put("swing.boldMetal", Boolean.FALSE);
    try {
        UIManager.setLookAndFeel(new MetalLookAndFeel());
        SwingUtilities.updateComponentTreeUI(rootComponent);
    } catch (javax.swing.UnsupportedLookAndFeelException e) {
        e.printStackTrace();
    }
このコードで PLAIN フォントへの変更と表示への反映が実行されます。 UIManager#setLookAndFeel メソッドは javax.swing.UnsupportedLookAndFeelException をスローする可能性があります(上のコードの場合は設定するのが MetalLookAndFeel なので少なくとも現時点では例外は発生しません)。
SwingUtilities#updateComponentTreeUI メソッドは現在のルックアンドフィールで UI プロパティを設定し再構築します。
引数の rootComponent には現在のルックアンドフィールで再構築するコンポーネントを指定します。 rootComponent がコンテナの場合にはそのコンテナ上のすべてのコンポーネントが 再構築されます。 よって rootComponent には BOLD フォントで表示されているすべてのコンポーネントの共通の親となる コンテナを設定します。 PLAIN フォント から BOLD フォントへの変更の場合にはコンポーネントのサイズが大きくなる可能性があります。 その結果すべてのコンポーネントがフレームに収まりきれずにフレームの再パックやサイズの変更が必要になるかもしれません。

swing.boldMetal に関しては API ドキュメントの javax.swing.plaf.metal.MetalLookAndFeel に記述があります。

下の TestFrame.java は swing.boldMetal の設定をコマンドラインとコードからテストするプログラムです。

//////////////////////// TestFrame.java ////////////////////////
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.metal.MetalLookAndFeel;

/**
 * J2SE 5.0以降の java コマンドにおいて
 * java -Dswing.boldMetal=false TestFrame
 * と起動するとメタルルックアンドフィールのデフォルトで
 * BOLD フォントが使用されるコンポーネントにおいて最初から
 * PLAIN フォントが使用される
 */
public class TestFrame extends JFrame implements ActionListener {

    JLabel label = new JLabel("ボタンを押すとデフォルトの" +
                              "Font Styleを変更します。");

    public TestFrame() {
        super("swing.boldMetal - Test");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JButton button = new JButton("BOLD ←→ PLAIN");
        button.addActionListener(this);
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(button);

        JPanel labelPanel = new JPanel();
        labelPanel.add(label);

        Container cp = getContentPane();
        cp.add(labelPanel, BorderLayout.CENTER);
        cp.add(buttonPanel, BorderLayout.SOUTH);
        setSize(450, 100);
        setVisible(true);
    }
//--------------------------------------------------------------------
    public void actionPerformed(ActionEvent e) {

        Boolean isBold = label.getFont().isBold() ? Boolean.FALSE
                                                  : Boolean.TRUE;

        // ボタン、ラベル、メニューなどのデフォルトで BOLD フォントが
        // 使用されるコンポーネントに関して isBold が
        // Boolean.FALSE なら PLAIN フォントへ
        // Boolean.TRUE なら BOLD フォントに設定する。
        // コンポーネントはすでに作成表示されているので
        // 変更を有効にするには try ブロック内の再構築処理が必要
        UIManager.put("swing.boldMetal", isBold);

        try {
            // swing.boldMetal の設定を反映した
            // MetalLookAndFeel オブジェクトを新たに作成し設定する
            UIManager.setLookAndFeel(new MetalLookAndFeel());

            // 現在のルックアンドフィールで引数のコンポーネント
            // (コンテナの場合はそれに含まれるすべてのコンポーネント)
            // の UI (見た目や振る舞い)を再構築し、引数の
            // コンポーネント以下のレイアウトの再配置と再描画を行う。
            // ここではコンテントペインを引数に指定しているが
            // 通常 BOLD から PLAIN へのフォントスタイルの変更は
            // コンポーネントのサイズが小さくなることがあっても
            // 大きくなることはないと思われるのでフォントスタイルが
            // 変更される最小範囲のコンテナ(あるいはコンポーネント)を
            // 指定すればよい。
            SwingUtilities.updateComponentTreeUI(getContentPane());

        } catch (UnsupportedLookAndFeelException exception) {
            System.out.println("ルックアンドフィールの設定に失敗:" +
                               exception);
        }
    }
//------------------------------- main -------------------------------
    public static void main(String[] args) {
        System.out.println("java.version: " +
                           System.getProperty("java.version"));

        // 下の行を有効にすると最初からPLAINフォントで表示される。
        // UIManager.put("swing.boldMetal", Boolean.FALSE);

        new TestFrame();
    }
}