TITLE:Cursorを砂時計に変更
#navi(../)
*Cursorを砂時計に変更 [#w760af9f]
>編集者:[[Terai Atsuhiro>terai]]~
作成日:2004-06-07~
更新日:&lastmod;

#contents

**概要 [#a06f1c43]
処理中、マウスカーソルを砂時計に変更します。

#screenshot

**サンプルコード [#r111147b]
#code{{
frame.setGlassPane(new MyGlassPane());
frame.getGlassPane().setVisible(false);
button.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    frame.getGlassPane().setVisible(true);
    button.setEnabled(false);
    Thread t = new Thread(new Runnable() {
      public void run() {
        longTask();
        EventQueue.invokeLater(new Runnable() {
          public void run() {
            frame.getGlassPane().setVisible(false);
            button.setEnabled(true);
          }
        });
      }
    });
    //t.setPriority(Thread.MIN_PRIORITY);
    t.start();
  }
});

class MyGlassPane extends JComponent {
  public MyGlassPane() {
    setOpaque(false);
    setFocusTraversalPolicy(new DefaultFocusTraversalPolicy() {
      public boolean accept(Component c) {return false;}
    });
    addKeyListener(new KeyAdapter() {});
    addMouseListener(new MouseAdapter() {});
    requestFocusInWindow();
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
  }
  public void setVisible(boolean flag) {
    super.setVisible(flag);
    setFocusTraversalPolicyProvider(flag);
  }
}
}}
-&jnlp;
-&jar;
-&zip;

**解説 [#a497267c]
上記のサンプルでは、カーソルを砂時計に変更し、なにもしないマウスリスナーなどを設定したGlassPaneをJFrame#setGlassPane()メソッドでフレームに追加しています。

スタートボタンがクリックされて処理が継続している間は、このGlassPaneが有効になり、マウス、キー、フォーカス移動などのイベントが、すべてGlassPaneに奪われるため、フレーム内のコンポーネントをアクセス不可にすることが出来ます。

このため、サンプルにあるsetEnabled(true)なJTextFieldの上にマウスポインタを移動しても、処理中はカーソルアイコンは砂時計のまま変化しません。

//**参考リンク
**コメント [#h83774c4]
-Tabキーで状態遷移しないようにするため、なにもしないFocusTraversalPolicyを追加しました。 -- [[terai]] &new{2005-04-18 (月) 10:51:25};
-2chのSwingスレが参考になります(763付近)。SwingWorkerを使う方法もあるようです。 -- [[terai]] &new{2005-04-19 (火) 17:27:58};
#code{{
button.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    frame.getGlassPane().setVisible(true);
    button.setEnabled(false);
    frame.getGlassPane().requestFocusInWindow();
    SwingWorker worker = new SwingWorker() {
      public Object construct() {
        return longTask();
      }
      public void finished() {
        frame.getGlassPane().setVisible(false);
        button.setEnabled(true);
        button.requestFocusInWindow(); 
      }
    };
    worker.start();
  }
});
}}
- 相当悩みました。JDialog だと同じことができないのは何でなんでしょうねぇ。。。 -- [[おれ]] &new{2006-05-17 (水) 16:33:12};
-- カーソルが変わらないのでしょうか? それともコンパイルエラーが出るとかでしょうか? -- [[terai]] &new{2006-05-17 (水) 17:59:14};
- 申し訳ない。カーソルが変わらないのだけれど、1.5系でコンパイルするとだめみたい。同じソースでも1.4系でコンパイルするとちゃんと変わる。1.5でのバグかな。。。 -- [[おれ]] &new{2006-05-18 (木) 12:58:11};
-- 追記。JDialog のコンストラクタに null を指定しているとこうなるようです。オーナフレームを指定してあげたら、1.5でもきちんと出ました。お騒がせしました。 -- [[おれ]]
-- なるほど、new JDialog((Frame)null);で試してみるとカーソルが変わらないですね。情報どうもでした。 -- [[terai]] &new{2006-05-18 (木) 21:45:15};
- DefaultFocusTraversalPolicy を使うように変更しました。 -- [[terai]] &new{2007-07-03 (火) 16:39:12};

#comment