今回もJava SE 7に導入予定の技術を紹介します。といっても、前回のProject Lambdaのように実装がないものではなく、既に存在している技術です。
読者の皆さんはSwingXというプロジェクトをご存じでしょうか?
標準ではSwingに含まれないコンポーネントなどを開発しているプロジェクトです。例えば、JTableやJListを拡張したJXTableやJXListなどがSwingXに含まれています。
残念ながら、SwingXは一昨年Sun Microsystemsからの支援が打ち切られてしまい、風前の灯火となっています。
そんなSwingXの中で、唯一Java SE 7に採用されることが決まったのが、今回取りあげるJXLayerです。
JXLayerは通常のSwingコンポーネントと異なり、単体で使用するコンポーネントではありません。ほかのコンポーネントと組み合わせて、そのコンポーネントを装飾させるためのコンポーネントです。
そういう意味ではJXLayerはJScrollPaneクラスに似た部分があります。
JScrollPaneクラスは単体で使用することはありません。ほかのコンポーネントと組み合わせ、そのコンポーネントをスクロールバーで装飾するために用います。
JScrolPaneクラスはスクロールバーに特化していますが、JXLayerは汎用に使用できる装飾のためのコンポーネントなのです。
JXLayerに至った背景
JXLayerを紹介する前に、なぜJXLayerが必要になったのかを少し考えてみましょう。
Javaで円や四角を描画するにはJava 2Dを使用します。Java 2Dには様々な機能があります。ベジェ曲線で描画したり、イメージに様々なエフェクトをかけることもできます。
では、Java 2DをSwingと一緒に使うにはどうしたらよいでしょうか?
その答えはJava 2Dを使用した描画を行うコンポーネントを継承して、サブクラスを作成するという方法です。
Swingのjavax.swing.JComponentクラスにはpaintComponentメソッドがあります。Java 2Dを使用するには、このメソッドをオーバーライドします。
例えば、四角を描画するためには次のようなクラスを作成します。
public class Square extends JComponent {
@Override
protected void paintComponent(Graphics g) {
g.setColor(Color.RED);
g.fillRect(10, 10, 50, 50);
}
}
しかし、これでは描画する種類が変化する度に、新たなサブクラスを作成しなくてはなりません。
Swingが設計されたのは10年以上前であり、継承がよく使用されていた時代です。しかし、現在では以前に比べると継承の重要性は減っています。
その代わりに使われるようになったのが、コンポジションです。
Swingでも、描画の機能をコンポジション化すれば、上記のようなサブクラスを作成する必要はありません。
例えば、Painterというインタフェースを定義し、JComponentクラスにsetPainterメソッドを追加すれば、もっと柔軟に描画のためのコードを記述することができます。
クラス図で書けば、現在の継承を使用した設計が図1、コンポジションを使用した設計が図2になります。
残念ながら、現在のSwingをコンポジションを利用した設計に変更するには、影響が大きすぎます。
そこで登場したのがJXLayerです。
JXLayerはコンポーネントを修飾するために、コンポジションを用いた設計になっています。
JXLayerの基本となるのがJXLayerクラスです。JXLayerクラスは修飾する対象のコンポーネントを保持し、描画機能を委譲するためにLayerUIインタフェースを使用します。
つまり、コンポーネントを修飾するための処理はLayerUIインタフェースを実装したクラスに記述します。
これをクラス図で表したのが図3です。
実際には、LayerUIに委譲するのは描画だけでなく、イベント処理などもあります。このため、LayerUIインタフェースを直接実装したクラスを作成するのではなく、LayerUIを実装したアブストラクトクラスのAbstractLayerUIクラスのサブクラスを使用するようにします。
では、次章からJXLayerの使い方について紹介していきます。