Go to Previous Page Go to Contents Go to Java Page Go to Next Page
New Features of Java2 SDK, Standard Edition, v1.4
 
 

Rollover Tool Bar

 
 

ボタンが浮き出る

 
 

JTabbedPane クラスにつづいて JToolBarですが、やはり追加された機能は 1 つだけです。ただし、追加されたのは RC1 からなので、Beta 版を使用している方は RC1 以降のバージョンにアップデートしてから、試してみてください。

最近のウィンドウズシステムでよくあるインタフェースとして、メニューやボタンの上にマウスポインタがあるときだけ、そのコンポーネントが浮き出るものがあります。

たとえば、以前はこんな感じでしたが、

図 1 以前から使用されていたスタイル

 

これがこんな感じになってきています。

図 2 浮き出るスタイル

いままで Swing の JToolBar ではこの浮き出るスタイルのツールバーは簡単には使うことができませんでした。v1.4 ではこのスタイルも使用できるようになりましたが、残念なことにまだ使えるのは JToolBar クラスだけのようです。できれば、JButton や JMenuBar でも使えるようになればいいのですが。 

 

 
  使い方は...  
 

浮き出るスタイルにするのはとても簡単です。

アプリケーションのソース ToolBarTest1.java

JToolBar クラスの setRollover メソッドを使用して、スタイルを決めます.このメソッドの引数は boolean で、true のときが浮き出るスタイル、false のときが従来スタイルになります。

    public ToolBarTest1() {
        JFrame frame = new JFrame("ToolBarTest");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(100, 100, 400, 200);
 
        JToolBar toolbar = new JToolBar();
        toolbar.setRollover(true);
  
        toolbar.add(new JButton("Button1"));
        toolbar.add(new JButton("Button2"));
        toolbar.add(new JButton("Button3"));
        toolbar.add(new JButton("Button4"));
 
        frame.getContentPane().add(toolbar, BorderLayout.NORTH);
 
        frame.setVisible(true);
    }

これだけで、浮き出るスタイルになります。

 

 
  どうやって実現しているか  
 

使い方は簡単なのですが、どやってこのスタイルを実現しているのでしょうか。

マウスポインタがコンポーネント上にあるかどうかは MouseEvent で知ることができます。そこで、マウスポインタがコンポーネント上に入ったらボタンを表示し、出たら表示しないようにすれば、ロールオーバーを実現できます。

また、ボタンの表示にはボーダを使用すればできそうです。

そこで、こんなサンプルを作ってみました。

アプリケーションのソース ToolBarTest2.java

このサンプルではツールバー上にボタンで MouseEvent を処理するようにし、マウスポインタがボタンの上にあるかどうかを調べています。

マウスポインタがボタン上にないときは、ボーダをつけないようにすればいいのですが、それだとボーダを設定したときにボタンの位置が変化してしまいます。そこで、javax.swing.border.EmptyBorder クラスを使用して、なにもないボーダを設定します。

もし、マウスポインタがボタン上にあれば、javax.swing.border.BevelBorder クラスを設定するようにしました。このとき、マウスがクリックされていたらへっこんだ形状、クリックされていないときには飛び出した形状になるようにします。

それではソースを説明していきます。

まず、コンストラクタでは使用するボーダを生成しておきます。

    private UIDefaults defaults = UIManager.getLookAndFeelDefaults();
    private Border rolloverBorder;
    private Border raisedBorder;
    private Border loweredBorder;
 
    public ToolBarTest2() {
        JFrame frame = new JFrame("ToolBarTest");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(100, 100, 400, 200);
 
        rolloverBorder = createRolloverBorder();
        raisedBorder = createRaisedBevelBorder();
        loweredBorder = createLoweredBevelBorder();

ボーダはプロパティにしており、createRolloverBorder メソッドなどで生成しておきます。また、UIDefaults クラスは画面の表示に関するデフォルト値を保持しているクラスです。たとえば、ウィンドウの背景色やフォントなどがあります。

それぞれのボーダを生成するためのメソッドも示しておきましょう。まずはロールオーバ用のボーダです。

    private Border createRolloverBorder() {
        return new CompoundBorder(new EmptyBorder(2, 2, 3, 2),
                                  new EmptyBorder(3, 3, 3, 3));
    }

javax.swing.border.CompoundBorder クラスは複合ボーダを作ります。コンストラクタには外側のボーダと内側のボーダの 2 つのボーダを指定します。このクラスを使用したのはボーダを直接ボタンに設定すると、ボタンの文字とボーダがくっつきすぎてしまうためです。そこで、ボタンの周りに 3 pixel だけ隙間を空けるようにしました。

外側の EmptyBorder の pixel 数は BevelBorder を設定したときにボタンの位置が動かないようにすることできめました。

同じように飛び出たボーダも CompountBorder クラスを使用しています。

    private Border createRaisedBevelBorder() {
        return new CompoundBorder(new BevelBorder(BevelBorder.RAISED,
                                  defaults.getColor("Button.light"),
                                  defaults.getColor("Button.highlight"),
                                  defaults.getColor("Button.shadow"),
                                  defaults.getColor("Button.darkShadow")),
                                  new EmptyBorder(3, 3, 3, 3));
    }

このボーダには BevelBorder を使用しています。本当は Metal Look & Feel だとボタンは BevelBorder ではなく、EtchedBorder なのですが、まぁいいでしょう。

defaults プロパティは UIDefaults オブジェクトで、ここではボタンの色に関するデフォルトを取得しています。

そして、rolloverBorder と同じように CompoundBorder オブジェクトを使用して複合化しています。

createLoweredBevelBorder メソッドは createRaisedBevelBorder メソッドの BevelBorder クラスのコンストラクタの第 1 引数が BevelBorder.RAISED から BelvelBorder.LOWERED に変わっただけです。

このようにして生成したボーダをボタンに設定します。コンストラクタの残りの部分でボーダの設定や、ツールバーへの登録を行っています。

        JToolBar toolbar = new JToolBar();
 
        JButton button = new JButton("Button1");
        toolbar.add(button);
        button.setBorder(rolloverBorder);
        button.addMouseListener(new RolloverAdapter());
 
        button = new JButton("Button2");
        toolbar.add(button);
        button.setBorder(rolloverBorder);
        button.addMouseListener(new RolloverAdapter());
 
        button = new JButton("Button3");
        toolbar.add(button);
        button.setBorder(rolloverBorder);
        button.addMouseListener(new RolloverAdapter());
 
        button = new JButton("Button4");
        toolbar.add(button);
        button.setBorder(rolloverBorder);
        button.addMouseListener(new RolloverAdapter());
 
        frame.getContentPane().add(toolbar, BorderLayout.NORTH);
 
        frame.setVisible(true);
    }

初期状態はボタンのボーダがない状態にするため、rolloverBorder を設定します。ボタンのオブジェクトごとにボーダを用意しなくてはいけないように思われますが、単一のボーダオブジェクトで OK です。

後は、マウスポインタがボタンの上にあるか、クリックされているかなどによってボーダを変化させる部分です。それは ToolBarTest2 クラスの内部クラスである RolloverAdapter クラスに実装しました。

RolloverAdapter クラスは MouseAdapter クラスの派生クラスなので、MouseEvent が発生すると呼び出されます。MouseEvent はマウスポインタがコンポーネントに入った、出た、ボタンが押された、ボタンを離した、クリックされたことで発生しますが、今回使用するのはコンポーネントに入った、出た、ボタンが押されたの 3 つの場合です。

    public class RolloverAdapter extends MouseAdapter {
 
        public void mousePressed(MouseEvent event){
            JButton button = (JButton)event.getSource();
            button.setBorder(loweredBorder);
        }
 
        public void mouseEntered(MouseEvent event){
            JButton button = (JButton)event.getSource();
            button.setBorder(raisedBorder);
        }
 
        public void mouseExited(MouseEvent event){
            JButton button = (JButton)event.getSource();
            button.setBorder(rolloverBorder);
        }
    }

ボタンが押されたとき mousePressed メソッドがコールされます。このときは、へっこんだ形状にするため loweredBorder をボーダとして設定します。

マウスポインタがボタンの上にきたときには、飛び出たようにするために raisedBorder を設定します。ボタンの上からマウスポインタが離れたときには、ボーダを描画しないように rolloverBorder を設定します。

これで、ToolBarTest1 と同様に動作させることができます。

 

 
  おまけ  
 

ツールバーではロールオーバスタイルを使用することができるようになりましたが、他のコンポーネントでもこのスタイルを使ってみたいとは思いませんか。特にメニューバーで使用したいと思うのは私だけでしょうか。

というわけで、JMenuBar でロールオーバをやってみました。

アプリケーションのソース MenuBarTest.java
RolloverMenu.java

ToolBarTest2 でロールオーバはできるのですが、MouseListener を add しなくてはいけないなど、使い勝手としてはいまいちでした。このサンプルではロールオーバが行えるメニューを JMenu の派生クラスとして作ってみました。

RolloverMenu クラスでは MouseEvent を処理するのに MouseListener を使うのではなく、processMouseEvent メソッドをオーバライドさせました。また、メニューが選択されているかどうかを調べるのには fireMenuSelected, fireMenuDeselected, fireMenuCanceled メソッドをオーバライドして使っています。

また、メニューがクリックされると背景色が反転してしまうので、反転させないために UI のクラスを派生させて使っています。

J2SE, v1.4 とは直接関係ないので、特にソースについての説明はしません。もし、興味がある方がいたら、ソースを眺めてみてください。

でも、これぐらいで実現できるのであれば、なんで JToolBar クラス以外でも使えるようにしてくれればいいのにと個人的には思います。J2SE, v1.4.1 があるかどうかは分かりませんが、もしリリースされたらそこで機能追加をしてくれるように希望してます。

今回使用したサンプルはここからダウンロードできます。

(Feb. 2002)

 
 
Go to Previous Page Go to Contents Go to Java Page Go to Next Page