前回、装飾に使用するSwingコンポーネントのJXLayerについて紹介しました。

 簡単におさらいすると、JXLayerはSwingコンポーネントにJava 2Dを使用して任意の描画やイメージ処理などの装飾を加えるためのコンポーネントです。

 JXLayerはコンポジションを使用した設計になっており、描画処理はLayerUIインタフェースに委譲しています。たとえばぼかしを行うLayerUIを実現したクラスを作成すれば、任意のSwingコンポーネントをぼかして表示することができます。

 今回は、前半でさらにJXLayerの使い方を紹介し、後半でJava SE 7でのJXLayerについて解説します。

GUIコンポーネントのロック

 まず紹介するのが、GUIコンポーネントをロックして、操作不可にする処理です。

 たとえば、モーダルなダイアログを表示させ、元のフレームは操作ができない場合を考えてみます。このような場合、元のフレームをぼかすなど操作不可だということがすぐに分るようすると、ユーザーが迷うことなく操作を続けることができます。

 モーダルダイアログはフレーム全体を操作不可にしてしまいますが、一部のコンポーネントだけを操作不可にしたいこともあります。

 たとえば、選択できないメニュー項目をグレーアウトすることなどは、よく行われています。

 JXLayerを使用すると、コンポーネントを操作不可にし、かつ操作不可だと分るように装飾することが可能です。

 ロックを可能にするためには、org.jdesktop.jxlayer.plaf.LayerUIインタフェースを実現したorg.jdesktop.jxlayer.plaf.ext.LockableUIクラスを使用します。

 LockableUIクラスはsetLockedメソッドを定義しています。引数にtrueを指定してsetLockedメソッドをコールすると、JXLayerオブジェクトが装飾しているコンポーネントをロックします。ロックを解除するには引数をfalseにしてsetLockedメソッドをコールします。

 LockableUIクラスのサブクラスを作成して、paintLayerメソッドをオーバーライドすると、ロックしている時だけpaintLayerメソッドがコールされます。

 また、前回使用したorg.jdesktop.jxlayer.plaf.BufferedLayerUIクラスと同じように、エフェクトを扱うことも可能です。この場合も、ロックしている間だけエフェクトが適用されます。

 ここでは、前回使用したぼかしを使って、コンポーネントをロックしてみます。

サンプルのソース (こちらからダウンロードできます)
BlurLockSample.java

 以下にBlurLockSampleクラスのコンストラクタを示します。

    private LockableUI blurUI;
  
    public BlurLockSample() {
        JFrame frame = new JFrame("JXLayer Blur Lock Sample");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 120);
 
        JPanel panel = createPanel();
 
        // JXLayerオブジェクトの生成
        JXLayer<JComponent> layer = new JXLayer<JComponent>(panel);
 
        // ぼかしを行うBufferedImageOpオブジェクト
        BufferedImageOp blurOp = createConvolveOp(5);
 
        // ロックが可能なLayerUIであるLockableUIを使用する
        blurUI = new LockableUI(new BufferedImageOpEffect(blurOp));
 
        layer.setUI(blurUI);
 
        frame.add(layer, BorderLayout.CENTER);
        frame.add(createCheckBox(), BorderLayout.SOUTH);
 
        frame.setVisible(true);
    }

 前回使用したぼかしを行うサンプル(BlurSample)とほとんど代わりはありません。異なるのは、BlurSampleではBufferedLayerUIクラスを使用していた部分をLockableUIクラスに変更したことです。

 JXLayerオブジェクトは装飾対象となるSwingコンポーネントをコンストラクタの引数として、生成します(青字部分)。

 ぼかしなどのイメージ処理を行うにはjava.awt.image.BufferedImageOpインタフェースを使用します。ぼかしを行う場合、前回説明したようにBufferedImageOpインタフェースを実装したjava.awt.image.ConvolveOpクラスを使用します。

 ここでは、ConvolveOpオブジェクトの生成は、オレンジで示したようにcreateConvolveOpメソッドで行っています。createConvolveOpメソッドは前回使用したものと同一です。

 そして、生成したConvolveOpオブジェクトを使用して、BufferedImageOpEffectオブジェクトを生成します。BufferedImageOpEffectクラスはその名の通りBufferedImageOpインタフェースを使用したイメージ処理を、装飾対象のコンポーネントに施すために使用します。

 最後に赤字で示したように、BufferedImageOpEffectオブジェクトをコンストラクタの引数にして、LockableUIオブジェクトを生成します。

 しかし、これだけではロックとそれに伴うぼかし処理は行われません。

 そこで、ロックを行わせるためにチェックボックスを配置するようにしました。

    private JComponent createCheckBox() {
        JPanel panel = new JPanel();

        // ロックの有無をチェックするチェックボックス
        JCheckBox box = new JCheckBox("Lock");
        box.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                JCheckBox box = (JCheckBox)event.getSource();

                if (box.isSelected()) {
                    // チェックされていたら、ロックする
                    blurUI.setLocked(true);
                } else {
                    // チェックされていなければ、ロックを解除
                    blurUI.setLocked(false);
                }
            }
        });

        panel.add(box);

        return panel;
    }

 チェックボックスをチェックすると、trueを引数にしてLockableUIオブジェクトのsetLockedメソッドをコールします。すると、JXLayerで装飾しているコンポーネントがロックされ、ぼかして表示されます。

 チェックが外されたら、falseを引数にしてsetLockedメソッドをコールします。すると、ロックが解除され、通常の表示に戻ります。

 では、コンパイルして、実行してみましょう。前回示したように、コンパイル、実行にはjxlayer.jarファイルをクラスパスに追加します。

 図1がロックしていない状態、図2がロックした状態です。

図1●BlurLockSampleの実行結果
図1●BlurLockSampleの実行結果

図2●ロックした場合
図2●ロックした場合