TITLE:Cursorを砂時計に変更

Cursorを砂時計に変更

編集者:Terai Atsuhiro
作成日:2004-06-07
更新日:2024-02-05 (月) 15:47:59

概要

処理中、マウスカーソルを砂時計に変更します。

#screenshot

サンプルコード

final FocusTraversalPolicy policy = new DefaultFocusTraversalPolicy() {
  public boolean accept(Component c) {return false;}
};
final FocusTraversalPolicy ftp = frame.getFocusTraversalPolicy();
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();
        EventQueue.invokeLater(new Runnable() {
          public void run() {
            frame.getGlassPane().setVisible(false);
            button.setEnabled(true);
            frame.setFocusTraversalPolicy(ftp);
          }
        });
      }
    });
    //t.setPriority(Thread.MIN_PRIORITY);
    t.start();
  }
});
//......
class MyGlassPane extends JPanel{
  public MyGlassPane() {
    setOpaque(false);
    addKeyListener(new KeyAdapter() {});
    addMouseListener(new MouseAdapter() {});
    super.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
  }
}
  • &jnlp;
  • &jar;
  • &zip;

解説

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

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

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

コメント

  • Tabキーで状態遷移しないようにするため、なにもしないFocusTraversalPolicyを追加しました。 -- terai
  • 2chのSwingスレが参考になります(763付近)。SwingWorkerを使う方法もあるようです。 -- terai
    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 だと同じことができないのは何でなんでしょうねぇ。。。 -- おれ
    • カーソルが変わらないのでしょうか? それともコンパイルエラーが出るとかでしょうか? -- terai
  • 申し訳ない。カーソルが変わらないのだけれど、1.5系でコンパイルするとだめみたい。同じソースでも1.4系でコンパイルするとちゃんと変わる。1.5でのバグかな。。。 -- おれ
    • 追記。JDialog のコンストラクタに null を指定しているとこうなるようです。オーナフレームを指定してあげたら、1.5でもきちんと出ました。お騒がせしました。 -- おれ
    • なるほど、new JDialog((Frame)null);で試してみるとカーソルが変わらないですね。情報どうもでした。 -- terai
  • DefaultFocusTraversalPolicy を使うように変更しました。 -- terai