Go to Contents Go to Java Page
J2SE 1.5 虎の穴
 
 

ウィンドウの位置にこだわる

 
 
Tiger ウィンドウを常に表示させたい
 
 

警告ダイアログやエラーを示すダイアログは常に前面に表示したいところです。この手の情報はユーザに気づいてもらわなければどうしようもないのですから。

ところが、今まで Java ではこれを制御することができませんでした。

もちろん、Window#toFront メソッドを使用すれば前面に表示することもできます。しかし、他のウィンドウにフォーカスが当たってしまうと後ろに隠れてしまうのです。

それがやっと Tiger で常に前面にするメソッドが加わりました。

    Window#setAlwaysOnTop(false)

Window クラスなので、派生クラスである Frame, Dialog, JWindow, JFrame, JDialog の各クラスも使用することができます。

サンプルのソース AlwaysOnTopSample1.java

ここでは JFrame クラスを使用してみました。

    public AlwaysOnTopSample1() {
        JFrame frame = new JFrame("AlwaysOnTopSample");
        frame.setSize(100, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        frame.setAlwaysOnTop(true);
 
        frame.setVisible(true);
    }

実行してみると確かに常に前面に表示されます。

ところで、setAlwaysOnTop メソッドはいつコールしてもかまわないのでしょうか。これも試してみましょう。

サンプルのソース AlwaysOnTopSample2.java

フレームにボタンをはって、ボタンが押されたら状態を変えるようにしてみました。

    public AlwaysOnTopSample2() {
        frame = new JFrame("AlwaysOnTopSample");
        frame.setSize(100, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        button = new JButton("Always on Top");
        button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent event) {
                    if (frame.isAlwaysOnTop()) {
                        button.setText("AlwaysOnTop Mode");
                        frame.setAlwaysOnTop(false);
                    } else {
                        button.setText("Normal Mode");
                        frame.setAlwaysOnTop(true);
                    }
                }
            });
        frame.getContentPane().add(button);
 
        frame.setVisible(true);
    }

ボタンが押されたら Window#isAlwaysOnTop メソッドを使用して現在の状態を調べ、AlwaysOnTop 状態であれば setAlwaysOnTop(false) をコールするようにします。逆に AlwaysOnTop 状態でなければ、AlwaysOnTop にします。

実行すると、ちゃんと切り替えられることが分かります。

ということは、いつ setAlwaysOnTop メソッドをコールしてもいいわけですね。

残念なのは、javax.swing.JOptionPane クラスです。showXXXXDialog メソッドの引数に AlwaysOnTop を指定できるようにしてもらいたかったからです。ところが、JOptionPane クラスはまったく変更なし。

ダイアログを表示させるのによく使われるのですから、こういうところも一緒に変更してくれればいいと思うのですが。前面に表示させるには JOptionPane#createDialog メソッドを使用して JDialog オブジェクトを生成し、その後生成した JDialog オブジェクトに対し setAlwaysOnTop(true) をコールするようにしなければなりません。

せっかくのユーティリティクラスなのにこんな手間をかけさせるなんて...

 

 
 
Tiger ウィンドウの位置にこだわりたくない
 
 

さて、話は変わります。

やはりウィンドウに関する話題ですが、ウィンドウの位置に関してです。

Java でない普通のアプリケーションを立ち上げると、OS がウィンドウの位置を調整してくれますよね。ちょっとずつずれて表示させるような感じです。

これが Tiger でできるようになりました。今まではデフォルトだと常に同じ場所にウィンドウが表示されてしまいます。他のアプリケーションのウィンドウの位置を Java のプログラム中で知ることはできないので、少しづつウィンドウをずらすということはできませんでした。

ようするにウィンドウを表示させる位置は OS にお任せというわけです。

これを行うには Window#setLocationByPlatform メソッドを使用します。

サンプルのソース WindowLocationSample1.java

5 つのフレームを表示させるだけのサンプルですが、表示を行う前に setLocationByPlatform(true) をコールしています。

    public WindowLocationSample1() {
        for (int i = 0; i < 5; i++) {
            JFrame frame = new JFrame("Sample");
            frame.setSize(100, 100);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             
            frame.setLocationByPlatform(true);
 
            frame.setVisible(true);
        }
    }

実行結果は次のようになりました。

ウィンドウ位置

ちゃんと並んでますね。

ところで、表示した後に setLocationByPlatform メソッドをコールしたらどうなるのでしょうか。後からでも並べ替えてくれるのでしょうか。やってみたら...

C:\examples>java WindowLocationSample1
Exception in thread "main" java.awt.IllegalComponentStateException: The window i
s showing on screen.
        at java.awt.Window.setLocationByPlatform(Window.java:2299)
        at WindowLocationSample1.(WindowLocationSample1.java:12)
        at WindowLocationSample1.main(WindowLocationSample1.java:17)

まぁ、当たり前ですね ^^;;

もう 1 つ実験してみます。

サンプルのソース WindowLocationSample2.java

setBounds メソッドや setLocation メソッドを使用してフレームの位置を指定した場合はどうなるかということです。

    public WindowLocationSample2() {
        for (int i = 0; i < 5; i++) {
            JFrame frame = new JFrame("Sample");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            frame.setBounds(100, 100, 100, 100);
            
            frame.setLocationByPlatform(true);

            frame.setVisible(true);
        }
    }

やってみたら、ちゃんと並んで表示されました。試しに、表示した後に setBounds メソッドをコールしたら、指定した位置に移動しました。

ということは setLocationByPlatform(true) をした場合に表示前に setBounds メソッド/setLocation メソッドで位置を指定しても無視されるということのようです。

 

 
 
Tiger おわりに
 
 

ちょっとしたことですが、こういうのがアプリケーションを作っているときに気になるところなのです。

特にダイアログが後ろに回ってしまう問題はいかんともしがたかったので、この機能追加は非常に喜ばしいです。

 

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

 

(Oct. 2004)

 
 
Go to Contents Go to Java Page