多重 Look & Feel の使用

このドキュメントは、最初に「The Swing Connection」で公開された記事に基づいています。


多重 Look & Feel を使用すると、通常の Look & Feel (デフォルト Look & Feel) を 1 つ以上の補助 Look & Feel で補足できます。たとえば、2 つの補助の Look & Feel (1 つは音声読み上げ用、もう 1 つは点字用) をデフォルト Look & Feel に追加することにより、Swing ベースアプリケーションが生成する通常の表示出力に加えて、同時に音声読み上げ出力や点字出力を提供できます。デフォルト Look & Feel は任意の通常の Look & Feel (Java や Windows の Look & Feel など) にすることができ、補助の Look & Feel と連携するための変更は不要です。

このドキュメントには次のセクションがあります。

このドキュメントを読み進める前に、プラグイン可能な Look & Feel の概念に習熟しておくようにしてください。基本的な情報については、「The Java Tutorial」のセクション「How to Set the Look and Feel」を参照してください。アーキテクチャーの詳細については、「Swing Connection」記事内のセクション「Pluggable look-and-feel architecture」を参照してください。


概要

javax.swing.plaf.multi パッケージ内のクラスは多重 Look & Feel を実装します。多重 Look & Feel は、UI オブジェクトを要求 (getUI メソッドを使用) するコンポーネントに応答して、複数の異なる Look & Feel から UI オブジェクトを透過的に作成し、同時にサポートします。

多重 Look & Feel を使用しない場合、特定の Look & Feel を拡張する開発者は Look & Feel をサポートするクラスの継承が必要になります。たとえば、多重 Look & Feel を使用しないで音声読み上げサポートを Java Look & Feel に追加する場合、開発者は Java Look & Feel のクラスを継承したクラスのグループを作成して、音声読み上げのサポートをこの新しいクラスに追加する必要があります。また、開発者が音声読み上げのサポートをその他の Look & Feel (Motif や Windows など) にも追加する場合、これらのクラスのサブクラスも作成する必要があります。

この方法には次のように少なくとも 2 つの短所があります。

多重 Look & Feel では、複数の Look & Feel を組み合わせることができるため、これらの 2 つの問題が同時に解決されます。最初の問題 (同じコードの別のコピーを使用する必要がある) は、開発者が特別な Look & Feel を作成してその他の Look & Feel と組み合わせることができるため、解決されます。

2 番目の問題 (特定の Look & Feel の使用を強制する必要がある) は、すでにロック済みの可能性があるデフォルト Look & Feel が何であれ、特別な Look & Feel を一緒に使用できるため、解決されます。

デフォルトの多重 Look & Feel の実装は、javax.swing.plaf.multi パッケージ内の MultiLookAndFeel クラスで表され、(そのままの) 多重 Look & Feel という名前です。


補助的な Look & Feel の使用方法

補助的な Look & Feel を Swing とともに使用するのは容易です。Swing に多重 Look & Feel を使用するように指示するには、すべてのアプリケーションで $JDKHOME/lib/swing.properties ファイルを変更して、swing.auxiliarylaf プロパティーの定義を含める必要があります。Swing は swing.auxiliarylaf プロパティーを LookAndFeel サブクラスのコンマ区切りのリストとみなしますが、これらのサブクラスは、デフォルト Look & Feel のほかに使用すべき補助的な Look & Feel を指定します。有効な LookAndFeel サブクラスが swing.auxiliarylaf プロパティーに少なくとも 1 つ指定されていると、Swing は自動的にその多重 Look & Feel を使用し、デフォルトおよび補助的な Look & Feel のロードとサポートを行います。

たとえば、アプリケーションが音声読み上げフィードバックをサポートする Look & Feel を使用し、香りを発するデバイスのサポートを追加する Look & Feel も使用するとします。音声読み上げ Look & Feel の名前は com.myco.TextTalkerLookAndFeel であり、香りのサポートを追加する Look & Feel の名前は com.smellco.OlfactoryLookAndFeel とします。

Swing に、これら 2 つの Look & Feel を使用し、同時にデフォルト Look & Feel も使用するように指示するには、アプリケーションで単に次の行を $JDKHOME/lib/swing.properties ファイルに追加するだけです。

    swing.auxiliarylaf=com.myco.TextTalkerLookAndFeel,
        com.smellco.OlfactoryLookAndFeel

この文は、コンポーネントの UI をデフォルト Look & Feel から直接取得する代わりに、多重 Look & Feel から自動的に取得するように Swing に指示します。結果として得られる多重 UI は、デフォルトおよび補助的な Look & Feel から UI を取得して維持する小さな委譲先です。この結果、多重 UI オブジェクトのメソッドが呼び出されると、多重 UI は、デフォルトおよび補助的な Look & Feel から取得した各 UI の同じメソッドを呼び出します。


補助的な Look & Feel を書く場合のヒント

補助的な Look & Feel は、デフォルト Look & Feel が提供する必要がある完全なサポートを提供する必要がない点を除いて、その他の Look & Feel と同様です。たとえば、音声読み上げフィードバックのみをサポートする補助的な Look & Feel は、ペイント用のコードを提供する必要はありません。また、すべてのコンポーネントをサポートする必要がない場合があります。たとえば、JSeparator は無視されることがあります。

補助的な Look & Feel は単純な傾向があるため、視覚的な Look & Feel よりも開発が容易な可能性があります。開発者は特別な機能を用意することのみに集中できます。

補助的な Look & Feel の主な目的はデフォルト Look & Feel を拡張することにあるため、補助的な Look & Feel は非視覚的になる傾向があります。ただし、補助的な Look & Feel も純粋な Look & Feel であるため、画面に情報をレンダリングしても構いません。

ほかの Look & Feel の場合と同様、補助的な Look & Feel を実装するには、javax.swing.LookAndFeel のサブクラスを記述し、javax.swing.plaf パッケージに定義されている FooUI クラスのサブクラスを作成します。


注意事項

次の段落では、補助的な Look & Feel の開発における一般的な推奨事項についていくつか説明します。

すべての初期化を実行する場合は installUI メソッドを使用し、すべてのクリーンアップを実行する場合は uninstallUI メソッドを使用します。

視覚的な Look & Feel を継承しないでください。

UI クラスが継承する UI 固有のすべてのメソッドをオーバーライドします。


UIDefaults の拡張

多くの場合、補助的な Look & Feel が「不完全」になる場合があります。つまり、コンポーネントの完全なセットをサポートする必要がない場合があります。たとえば、補助的な Look & Feel は ButtonUI サブクラスを提供して、LabelUI サブクラスを提供しない場合があります。こうした選択は可能であり、多重 Look & Feel はこのような状況を適切に処理します。

ただしデフォルトでは、Swing は、Look & Feel に UI オブジェクトを要求して Look & Feel がその UI をサポートしない場合、エラーメッセージを発行します。特に、補助的な Look & Feel の開発者が特定のコンポーネントをサポートする予定がない場合、このメッセージは迷惑な場合があります。

幸い、UIDefaults クラスのサブクラスを作成し、そのインスタンスを LookAndFeel クラスの getDefaults メソッドから返すことにより、このエラーメッセージを回避できます。たとえば、

public class MyAuxLookAndFeel extends LookAndFeel {
...
public UIDefaults getDefaults() {
UIDefaults table =
            new MyAuxUIDefaults();
Object[] uiDefaults = {
"ButtonUI", "MyAuxButtonUI",
...
}
table.putDefaults(uiDefaults);
return table;
}
}

class MyAuxUIDefaults extends UIDefaults {
protected void getUIError(String msg) {
//System.err.println
        //   ("An annoying message!");
}
}

上記の例では、MyAux という補助的な Look & Feel は getUIError メソッドをオーバーライドする UIDefaults サブクラスを作成します。getUIError メソッドは、Swing が Look & Feel の UI オブジェクトを検出できなかった場合に呼び出されるメソッドです。単にこのメソッドで何もしなければ、エラーメッセージを回避できます。


その他の UI オブジェクトの調査

まれに、補助的な Look & Feel の UI オブジェクトが、コンポーネントに使用されるデフォルト UI オブジェクトに関心がある場合があります。この場合、補助的な Look & Feel の UI オブジェクトは getUI メソッドを呼び出すことで、コンポーネントから UI を取得できます。返される UI は、いずれかの多重 Look & Feel UI クラス (MultiButtonUI など) のインスタンスです。補助的な Look & Feel の UI オブジェクトは、返されたオブジェクトの getUIs メソッドを呼び出して、多重 UI によって処理されるすべての UI オブジェクトの完全なリストが含まれた配列を取得できます。最初の要素は、デフォルトの Look & Feel から作成された UI であることが保証されます。


多重 Look & Feel の実装方法

javax.swing.plaf.multi.MultiLookAndFeel で表される多重 Look & Feel は、すべての開発者およびユーザーに対して透過的であるように作られています。それは「とにかく動作」すべきであり、ユーザーが Swing に補助的な Look & Feel を使用するように指示した場合にのみ使用されます。

多重 Look & Feel が使用されている場合、各コンポーネントに関連付けられた UI オブジェクトの型は、現在使用中の任意の補助的な Look & Feel がそのコンポーネントをサポートするかどうかにより異なります。その場合、コンポーネントの UI オブジェクトは多重 UI のインスタンスです。デフォルト Look & Feel のみがコンポーネントをサポートする場合、補助的な Look & Feel がインストールされていないかのように、そのコンポーネントは UI オブジェクトをデフォルト Look & Feel から取得します。

多重 UI オブジェクトは、UI オブジェクトをデフォルトおよび補助的な Look & Feel から取得して維持し、これらの UI を次の方法で参照します。

すべての場合で、デフォルト Look & Feel から取得した UI オブジェクトが最初に処理され、補助的な Look & Feel は swing.auxiliarylaf プロパティーで指定されている順序で処理されます。


カスタム多重 Look & Feel の提供方法

多重 Look & Feel の動作が代わりの多重 Look & Feel を必要としないほど柔軟になるのが望ましいことですが、Swing では、ユーザーは使用する別の多重 Look & Feel を指定できます。

これを実行するには、ユーザーが $JDKHOME/lib/swing.properties ファイルを変更して swing.plaf.multiplexinglaf プロパティーの定義を含めるだけです。その後、Swing は swing.plaf.multiplexinglaf プロパティーを、多重をサポートする LookAndFeel のサブクラスとみなします。

たとえば、多重 Look & Feel (javax.swing.plaf.multi.MultiLookAndFeel) よりもニーズに合う com.myco.SuperMultiLookAndFeel で表される多重 Look & Feel をユーザーが持っている場合、ユーザーは次の行を $JDKHOME/lib/swing.properties に含めることができます。

swing.plaf.multiplexinglaf = com.myco.SuperMultiLookAndFeel

この文は Swing に javax.swing.plaf.multi.MultiLookAndFeel の代わりに com.myco.SuperMultiLookAndFeel を使用するように指示します。ただし、補助的な Look & Feel の供給者は標準の多重 Look & Feel に対して開発しテストしている可能性が高いため、この種類の文を使用する場合は注意してください。