このドキュメントは、最初に「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 を継承しないでください。
補助的な Look & Feel の UI クラスを視覚的な Look & Feel の UI クラスのサブクラスとして実装しないことをお勧めします。理由は次のとおりです。リスナーをコンポーネントオブジェクトにインストールしたりコンポーネントを画面にレンダリングしたりするコードを誤って継承する場合があるためです。その結果、補助的な Look & Feel はデフォルト Look & Feel と協調するのではなく競合する可能性があります。
代わりに、補助的な Look & Feel の UI クラスが javax.swing.plaf
パッケージの抽象 UI クラスを直接継承することをお勧めします。この方法を使用すると、補助的な Look & Feel がデフォルト Look & Feel と競合することを避けることができます。
UI クラスが継承する UI 固有のすべてのメソッドをオーバーライドします。
補助的な Look & Feel の各 UI クラスは派生元の javax.swing.plaf
UI クラスに定義されているメソッドをオーバーライドすることをお勧めします。この推奨事項の理由は、視覚的な Look & Feel を継承しない理由と同様です。たとえば、すべての UI クラスの派生元の ComponentUI
クラスは update
メソッドのデフォルト実装を提供します。このデフォルト実装では、コンポーネントが不透明の場合に画面にペイントします。非視覚的で補助的な Look & Feel の UI クラスがこのメソッドをオーバーライドしないと、すべてが不透明なコンポーネントが空白領域として画面に表示されてしまいます。
多くの場合、補助的な 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 オブジェクトを検出できなかった場合に呼び出されるメソッドです。単にこのメソッドで何もしなければ、エラーメッセージを回避できます。
まれに、補助的な Look & Feel の UI オブジェクトが、コンポーネントに使用されるデフォルト UI オブジェクトに関心がある場合があります。この場合、補助的な Look & Feel の UI オブジェクトは getUI
メソッドを呼び出すことで、コンポーネントから UI を取得できます。返される UI は、いずれかの多重 Look & Feel UI クラス (MultiButtonUI
など) のインスタンスです。補助的な Look & Feel の UI オブジェクトは、返されたオブジェクトの getUIs
メソッドを呼び出して、多重 UI によって処理されるすべての UI オブジェクトの完全なリストが含まれた配列を取得できます。最初の要素は、デフォルトの Look & Feel から作成された UI であることが保証されます。
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 を次の方法で参照します。
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 を指定できます。
これを実行するには、ユーザーが $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 に対して開発しテストしている可能性が高いため、この種類の文を使用する場合は注意してください。