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);
     frame.setFocusTraversalPolicy(policy);
     Thread t = new Thread(new Runnable() {
       public void run() {
         longTask();
         SwingUtilities.invokeLater(new Runnable() {
           public void run() {
             frame.getGlassPane().setVisible(false);
             button.setEnabled(true);
             frame.setFocusTraversalPolicy(ftp);
           }
         });
       }
     });
     //t.setPriority(Thread.MIN_PRIORITY);
     t.start();
   }
 });

 final FocusTraversalPolicy policy = new FocusTraversalPolicy() {
   public Component getFirstComponent(Container focusCycleRoot) {
     return null;
   }
   public Component getLastComponent(Container fcr) {
     return null;
   }
   public Component getComponentAfter(Container fcr, Component c) {
     return null;
   }
   public Component getComponentBefore(Container fcr, Component c) {
     return null;
   }
   public Component getDefaultComponent(Container fcr) {
     return null;
   }
 };
 final FocusTraversalPolicy ftp = frame.getFocusTraversalPolicy();

 class MyGlassPane extends JPanel{
   public MyGlassPane() {
     setOpaque(false);
     addKeyListener(new KeyAdapter() {});
     addMouseListener(new MouseAdapter() {});
     super.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
   }
 }
}}
-&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};
 button.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) {
     frame.getGlassPane().setVisible(true);
     button.setEnabled(false);
     frame.setFocusTraversalPolicy(policy);
     frame.getGlassPane().requestFocusInWindow();
     SwingWorker worker = new SwingWorker() {
       public Object construct() {
         return longTask();
       }
       public void finished() {
         frame.getGlassPane().setVisible(false);
         button.setEnabled(true);
         frame.setFocusTraversalPolicy(ftp);
         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};

#comment