Swing/WaitCursor のバックアップの現在との差分(No.3)
- バックアップ一覧
- 差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/WaitCursor へ行く。
- 1 (2007-05-07 (月) 13:57:16)
- 2 (2007-07-03 (火) 16:38:28)
- 3 (2007-07-03 (火) 19:06:04)
- 4 (2007-07-08 (日) 05:51:50)
- 5 (2007-08-27 (月) 19:24:15)
- 6 (2008-04-15 (火) 16:58:10)
- 7 (2008-04-25 (金) 20:55:09)
- 8 (2008-11-10 (月) 20:33:08)
- 9 (2011-03-18 (金) 19:09:12)
- 10 (2011-03-26 (土) 23:15:00)
- 11 (2011-08-25 (木) 18:33:32)
- 12 (2011-10-10 (月) 19:22:06)
- 13 (2013-04-10 (水) 02:37:38)
- 14 (2013-07-26 (金) 01:31:36)
- 15 (2013-08-18 (日) 04:30:36)
- 16 (2013-08-20 (火) 14:27:40)
- 17 (2013-08-21 (水) 20:51:02)
- 18 (2013-09-07 (土) 00:27:58)
- 19 (2014-01-14 (火) 08:32:09)
- 20 (2014-01-14 (火) 14:13:39)
- 21 (2014-09-18 (木) 02:32:07)
- 22 (2014-10-25 (土) 23:45:44)
- 23 (2014-11-18 (火) 19:16:27)
- 24 (2014-11-25 (火) 03:03:31)
- 25 (2015-10-09 (金) 16:32:32)
- 26 (2016-02-06 (土) 18:18:27)
- 27 (2016-06-03 (金) 13:27:52)
- 28 (2016-08-18 (木) 15:12:02)
- 29 (2017-08-23 (水) 18:43:57)
- 30 (2017-11-02 (木) 15:32:16)
- 31 (2018-06-27 (水) 19:29:34)
- 32 (2018-08-24 (金) 15:07:25)
- 33 (2018-10-14 (日) 16:36:06)
- 34 (2018-10-20 (土) 19:05:14)
- 35 (2020-10-18 (日) 18:44:07)
- 36 (2022-08-12 (金) 00:59:10)
- 37 (2024-02-05 (月) 15:47:59)
- 追加された行はこの色です。
- 削除された行はこの色です。
TITLE:Cursorを砂時計に変更 #navi(../) *Cursorを砂時計に変更 [#w760af9f] >編集者:[[Terai Atsuhiro>terai]]~ 作成日:2004-06-07~ 更新日:&lastmod; --- category: swing folder: WaitCursor title: Cursorを砂時計に変更 tags: [Cursor, GlassPane, FocusTraversalPolicy, SwingWorker] author: aterai pubdate: 2004-06-07T13:57:16+09:00 description: バックグラウンドで処理が実行されている間は、Cursorに砂時計が設定されたGlassPaneを有効にします。 image: https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTWfYWDbsI/AAAAAAAAApU/rldJwQuVm-8/s800/WaitCursor.png --- * 概要 [#summary] バックグラウンドで処理が実行されている間は、`Cursor`に砂時計が設定された`GlassPane`を有効にします。 #contents #download(https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTWfYWDbsI/AAAAAAAAApU/rldJwQuVm-8/s800/WaitCursor.png) **概要 [#a06f1c43] 処理中、マウスカーソルを砂時計に変更します。 #screenshot **サンプルコード [#r111147b] #code{{ final FocusTraversalPolicy policy = new DefaultFocusTraversalPolicy() { public boolean accept(Component c) {return false;} }; final FocusTraversalPolicy ftp = frame.getFocusTraversalPolicy(); frame.setGlassPane(new MyGlassPane()); * サンプルコード [#sourcecode] #code(link){{ frame.setGlassPane(new LockingGlassPane()); frame.getGlassPane().setVisible(false); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @Override 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); } }); new SwingWorker() { @Override public Object doInBackground() { doSomeLongTask(); return "Done"; } }); //t.setPriority(Thread.MIN_PRIORITY); t.start(); @Override public void done() { frame.getGlassPane().setVisible(false); button.setEnabled(true); } }.execute(); } }); //...... class MyGlassPane extends JPanel{ public MyGlassPane() { // ... class LockingGlassPane extends JComponent { public LockingGlassPane() { setOpaque(false); setFocusTraversalPolicy(new DefaultFocusTraversalPolicy() { @Override public boolean accept(Component c) { return false; } }); addKeyListener(new KeyAdapter() {}); addMouseListener(new MouseAdapter() {}); super.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); requestFocusInWindow(); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); } @Override public void setVisible(boolean flag) { super.setVisible(flag); setFocusTraversalPolicyProvider(flag); } } }} -&jnlp; -&jar; -&zip; **解説 [#a497267c] 上記のサンプルでは、カーソルを砂時計に変更し、なにもしないマウスリスナーなどを設定したGlassPaneをJFrame#setGlassPane()メソッドでフレームに追加しています。 * 解説 [#explanation] 上記のサンプルでは、カーソルを砂時計に変更し、なにもしないマウスリスナーなどを設定した`GlassPane`を`JFrame#setGlassPane()`メソッドでフレームに追加しています。 スタートボタンがクリックされて処理が継続している間は、このGlassPaneが有効になり、マウス、キー、フォーカス移動などのイベントが、すべてGlassPaneに奪われるため、フレーム内のコンポーネントをアクセス不可にすることが出来ます。 スタートボタンがクリックされて処理が継続している間はこの`GlassPane`が有効になり、マウス、キー入力、フォーカス移動などのイベントがすべて`GlassPane`に奪われるため、フレーム内のコンポーネントがアクセス不可状態になります。 このため、サンプルにあるsetEnabled(true)なJTextFieldの上にマウスポインタを移動しても、処理中はカーソルアイコンは砂時計のまま変化しません。 このため、サンプルにある`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}; ---- KBD{Tab}キーなどによるフォーカス移動を禁止する場合は、`GlassPane`に以下のような設定を行います。 - どのコンポーネントにもフォーカス移動できない`FocusTraversalPolicy`を設定する #code{{ 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(); setFocusTraversalPolicy(new DefaultFocusTraversalPolicy() { @Override public boolean accept(Component c) { return false; } }); }} - 相当悩みました。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}; - または、`TraversalKeys`を空にする -- 参考: [https://community.oracle.com/thread/1375257 Swing - How to display "Loading data..." to the user] #code{{ Set<AWTKeyStroke> s = Collections.emptySet(); setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, s); setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, s); }} ---- `Mnemonic`なども禁止したい場合は、以下のような`GlassPane`を使用する方法があります(参考: [http://weblogs.java.net/blog/alexfromsun/archive/2008/01/ Disabling Swing Containers, the final solution?])。 #code{{ class LockingGlassPane extends JComponent { public LockingGlassPane() { setOpaque(false); super.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); } @Override public void setVisible(boolean isVisible) { boolean oldVisible = isVisible(); super.setVisible(isVisible); JRootPane rootPane = SwingUtilities.getRootPane(this); if (rootPane != null && isVisible() != oldVisible) { rootPane.getLayeredPane().setVisible(!isVisible); } } @Override protected void paintComponent(Graphics g) { JRootPane rootPane = SwingUtilities.getRootPane(this); if (rootPane != null) { // http://weblogs.java.net/blog/alexfromsun/archive/2008/01/ // it is important to call print() instead of paint() here // because print() doesn't affect the frame's double buffer rootPane.getLayeredPane().print(g); } super.paintComponent(g); } } }} ---- - `JDK 1.6.0`の場合、[https://tips4java.wordpress.com/2008/11/07/disabled-glass-pane/ Disabled Glass Pane « Java Tips Weblog]のようにキー入力を無効にするキーリスナーを追加する方法もある -- この方法は、`JDK 1.5.0`などの場合、`WindowsLookAndFeel`で、KBD{Alt}キーを押すとメニューバーにフォーカスが移動する場合がある ---- - `JDK 1.7.0`の場合、`JLayer`を使用して特定のコンポーネントだけ入力不可、かつカーソルを砂時計に変更するなどの設定が可能になった -- [[JLayerで指定したコンポーネントへの入力を禁止>Swing/DisableInputLayer]] に移動 * 参考リンク [#reference] - [https://community.oracle.com/thread/1375257 Swing - How to display "Loading data..." to the user] - [http://weblogs.java.net/blog/alexfromsun/archive/2008/01/ Disabling Swing Containers, the final solution?] -- [[JInternalFrameをModalにする>Swing/ModalInternalFrame]] - [https://tips4java.wordpress.com/2008/11/07/disabled-glass-pane/ Disabled Glass Pane « Java Tips Weblog] * コメント [#comment] #comment - KBD{Tab}キーで状態遷移しないようにするため、なにもしない`FocusTraversalPolicy`を追加しました。 -- &user(aterai); &new{2005-04-18 (月) 10:51:25}; - 相当悩みました。`JDialog`だと同じことができないのは何でなんでしょうねぇ。。。 -- &user(おれ); &new{2006-05-17 (水) 16:33:12}; -- カーソルが変わらないのでしょうか? それともコンパイルエラーが出るとかでしょうか? -- &user(aterai); &new{2006-05-17 (水) 17:59:14}; - 申し訳ない。カーソルが変わらないのだけれど、`1.5`系でコンパイルするとだめみたい。同じソースでも`1.4`系でコンパイルするとちゃんと変わる。`1.5`でのバグかな。。。 -- &user(おれ); &new{2006-05-18 (木) 12:58:11}; -- 追記。`JDialog`のコンストラクタに`null`を指定しているとこうなるようです。オーナフレームを指定してあげたら、`1.5`でもきちんと出ました。お騒がせしました。 -- &user(おれ); -- なるほど、`new JDialog((Frame)null);`で試してみるとカーソルが変わらないですね。情報どうもでした。 -- &user(aterai); &new{2006-05-18 (木) 21:45:15}; - `DefaultFocusTraversalPolicy`を使うように変更しました。 -- &user(aterai); &new{2007-07-03 (火) 16:39:12}; - `GlassPane`で、`FocusTraversalPolicy`を使わず、`print`を使って`Mnemonic`などをブロックするように変更しました。 -- &user(aterai); &new{2008-04-15 (火) 17:14:09}; - `SwingWorker`を使うように変更。 -- &user(aterai); &new{2011-03-26 (土) 23:21:11}; - 入力抑制であれば`AWTEventListener`を追加して`InputEvent`を`consume`しちゃえば良いのでは・・・? -- &user(sawshun); &new{2014-01-14 (火) 08:32:09}; -- `AWTEventListener`を使うのは便利な方法だと思いますが、セキュリティマネージャの設定によっては`SecurityException`が発生したり、ドキュメントには「[https://docs.oracle.com/javase/jp/8/docs/api/java/awt/Toolkit.html#addAWTEventListener-java.awt.event.AWTEventListener-long- アクセシビリティー、イベントの記録と再生、および診断トレースなどの特別な機能をサポートすることを主な目的としているので、アプリケーションの使用では推奨されません。]」的な注意事項があるので、使い所を考慮する必要がありそうです。このサンプルのような場合で`InputEvent#consume()`を使うなら`1.7`以上で`JLayer`を使用する方が無難かもしれません。 -- &user(aterai); &new{2014-01-14 (火) 14:13:39}; #comment