このドキュメントは、最初に「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を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は、ペイント用のコードを提供する必要はありません。 また、すべてのコンポーネントをサポートする必要がない場合があります。たとえば、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が設定されると、installUIおよびuninstallUIメソッドが呼び出されます。installUIメソッドにより、新しいUIオブジェクトはコンポーネントおよびそのデータ・モデルにリスナーを追加できます。 同様に、uninstallUIメソッドにより、そのUIオブジェクトはリスナーを削除できます。
視覚的なLook & Feelを継承しないでください。
補助ルック・アンド・フィールのUIクラスをビジュアル・ルック・アンド・フィールのUIクラスのサブクラスとして実装しないことをお薦めします。なんでないの? コンポーネント・オブジェクトにリスナーをインストールするコードや、表示上にコンポーネントをレンダリングするコードを誤って継承する場合があります。その結果、補助的なルック・アンド・フィールは、デフォルト・ルック・アンド・フィールと連携するのではなく、競合します。
かわりに、補助ルック・アンド・フィールのUIクラスでは、javax.swing.plafパッケージの抽象UIクラスを直接拡張することをお薦めします。この戦略を使用することで、補助的なルック・アンド・フィールの開発者は、デフォルトのルック・アンド・フィールとの競合を回避できます。
UIクラスが継承するUI固有のすべてのメソッドをオーバーライドします。
補助的なLook & Feelの各UIクラスは派生元のjavax.swing.plafUIクラスに定義されているメソッドをオーバーライドすることをお薦めします。この推奨事項の理由は、視覚的なLook & Feelを継承しない理由と同様です。 たとえば、すべてのUIクラスの派生元のComponentUIクラスはupdateメソッドのデフォルト実装を提供します。 このデフォルト実装では、コンポーネントが不透明の場合に画面にペイントします。 非視覚的で補助的なLook & FeelのUIクラスがこのメソッドをオーバーライドしないと、すべてが不透明なコンポーネントが空白領域として画面に表示されてしまいます。
多くの場合、補助的なルック・アンド・フィールを「不完全」にしたい場合があります。つまり、コンポーネントの完全なセットをサポートする必要がない場合があります。 たとえば、補助的な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という名前の補助ルック・アンド・フィールによって、getUIErrorメソッドをオーバーライドするUIDefaultsサブクラスが作成されます。getUIErrorメソッドは、Swingがルック・アンド・フィールでUIオブジェクトを見つけられない場合に呼び出されるメソッドです。このメソッドで何もしないだけで、エラー・メッセージを回避できます。
まれに、補助ルック・アンド・フィールのUIオブジェクトが、コンポーネントで使用されるデフォルトのUIオブジェクトに関心がある場合があります。このような場合、補助ルック・アンド・フィールからUIオブジェクトは、そのgetUIメソッドをコールしてコンポーネントからUIを取得できます。返されるUIは、多重化ルック・アンド・フィールUIクラスの1つのインスタンスです(たとえば、MultiButtonUI)。 補助的なLook & FeelのUIオブジェクトは、返されたオブジェクトのgetUIsメソッドを呼び出して、多重UIによって処理されるすべてのUIオブジェクトの完全なリストが含まれた配列を取得できます。 最初の要素は、デフォルトのLook & Feelから作成されたUIであることが保証されます。
多重化ルック・アンド・フィール(javax.swing.plaf.multi.MultiLookAndFeelで表される)は、すべての開発者およびユーザーに対して透過的です。これは"just work"であり、ユーザがSwingに補助ルックアンドフィールを使用するように指示した場合にのみ使用されます。
多重Look & Feelが使用されている場合、各コンポーネントに関連付けられたUIオブジェクトの型は、現在使用中の任意の補助的なLook & Feelがそのコンポーネントをサポートするかどうかにより異なります。 その場合、コンポーネントのUIオブジェクトは多重UIのインスタンスです。 デフォルトLook & Feelのみがコンポーネントをサポートする場合、補助的なLook & Feelがインストールされていないかのように、そのコンポーネントはUIオブジェクトをデフォルトLook & Feelから取得します。
多重UIオブジェクトは、UIオブジェクトをデフォルトおよび補助的なLook & Feelから取得して維持し、これらのUIを次の方法で参照します。
swing.auxiliarylafプロパティで指定されている順序で、それぞれの補助的なLook &Feelから作成されます。getPreferredSizeメソッドが呼び出されると、このUIは、デフォルトLook & Feelから取得したUIのgetPreferredSizeの呼出しの結果のみを返します。 また、それぞれの補助的なLook &FeelのUIオブジェクトのgetPreferredSizeメソッドも呼び出されますが、戻り値は無視されます。 installUIメソッドを呼び出すと、多重UIは、デフォルトLook & Feelから取得したUIと、補助的なファクトリから取得したUIでinstallUIを呼び出します。 すべての場合で、デフォルトLook & Feelから取得したUIオブジェクトが最初に処理され、補助的なLook & Feelはswing.auxiliarylafプロパティで指定されている順序で処理されます。
多重Look &Feelの動作が代わりの多重Look &Feelを必要としないほど柔軟になるのが望ましいことですが、Swingでは、ユーザーは使用する別の多重Look &Feelを指定できます。
そのためには、swing.plaf.multiplexinglafプロパティの定義を含めるように$JDKHOME/lib/swing.propertiesファイルを変更する必要があります。その後、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に対して開発しテストしている可能性が高いため、この種類の文を使用する場合は注意してください。