5

ユーザーにボタンを押してバックグラウンド スレッドを開始させたい。

スレッドの処理中に、次の 2 つのことを実行したいと考えています。

1) WAIT_CURSOR が表示されます。

2) アプリケーションはマウス イベントに応答しません。

setCursorのドキュメントによると、「このコンポーネントの contains メソッドが現在のカーソル位置に対して true を返し、このコンポーネントが表示可能、表示可能、および有効になっている場合、このカーソル画像が表示されます。」.

このバックグラウンド スレッドの処理中にアプリケーションを無効にしたい。

必要な機能を取得する方法はありますか?

import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class WaitCursor extends JFrame
{
    private static final long    serialVersionUID    = 1L;

    public WaitCursor()
    {
        setResizable(false);

        setName(getClass().getSimpleName());
        setTitle("My Frame");
        setSize(300, 300);

        getContentPane().add(new MyButtonPanel());

    }

    private class MyButtonPanel extends JPanel
    {

        private static final long    serialVersionUID    = 1L;

        public MyButtonPanel()
        {
            JButton btnStart = new JButton("Start");
            btnStart.addActionListener(new BtnStartActionListener());
            add(btnStart);
        }

        private class BtnStartActionListener implements ActionListener
        {
            public void actionPerformed(ActionEvent e)
            {
                // Change to WAIT_CURSOR
                Component root = SwingUtilities.getRoot((JButton) e.getSource());
                JOptionPane.showMessageDialog(root, "Wait 10 seconds");
                root.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

                // TODO: Disabling the root component prevents the WAIT_CURSOR from being displayed
                root.setEnabled(false);
                new Thread(new TimeKiller(root)).start();
            }
        }
    }

    private class TimeKiller implements Runnable
    {
        Component    _root;

        public TimeKiller(Component root)
        {
            _root = root;
        }

        public void run()
        {
            try
            {
                Thread.sleep(10 * 1000);
            }
            catch (InterruptedException e)
            {
                // Ignore it
            }
            // Change back to DEFAULT CURSOR
            JOptionPane.showMessageDialog(_root, "Done waiting");
            _root.setCursor(Cursor.getDefaultCursor());
            _root.setEnabled(true);
        }
    }

    private static void createAndShowGUI()
    {
        // Create and set up the window.
        WaitCursor frame = new WaitCursor();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    createAndShowGUI();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    System.exit(0);
                }
            }
        });
    }

}
4

2 に答える 2

5

これを無効にする 1 つの方法は、ガラス ペインを使用してマウス入力をブロックすることです。

例えば:

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;

import javax.swing.*;

@SuppressWarnings("serial")
public class WaitCursor2 extends JPanel {

   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private JComponent glassPane;
   private JButton runBackgroundProcBtn;
   private JTextArea textarea = new JTextArea(15, 30);

   public WaitCursor2(JComponent glassPane) {
      this.glassPane = glassPane;
      glassPane.setFocusable(true);
      glassPane.addMouseListener(new MouseAdapter() {
      }); // so it will trap mouse events.

      add(new JTextField(10));
      add(runBackgroundProcBtn = new JButton(new AbstractAction(
            "Run Background Process") {

         @Override
         public void actionPerformed(ActionEvent arg0) {
            runBackgroundProcessAction();
         }
      }));
      add(new JScrollPane(textarea));
   }

   private void runBackgroundProcessAction() {
      disableSystem(true);
      glassPane.setVisible(true);
      new SwingWorker<Void, Void>() {
         @Override
         protected Void doInBackground() throws Exception {
            long sleepTime = 5000;
            Thread.sleep(sleepTime);
            return null;
         }

         @Override
         protected void done() {
            disableSystem(false);
         }
      }.execute();
   }

   public void disableSystem(boolean disable) {
      glassPane.setVisible(disable);
      runBackgroundProcBtn.setEnabled(!disable);
      if (disable) {
         System.out.println("started");
         glassPane.requestFocusInWindow(); // so can't add text to text components
         glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
      } else {
         System.out.println("done");
         glassPane.setCursor(Cursor.getDefaultCursor());
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("WaitCursor2");
      WaitCursor2 mainPanel = new WaitCursor2((JComponent) frame.getGlassPane());

      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

ガラス ペインが可視に設定され、MouseListener が指定されている場合、ガラス ペインはマウス イベントをトラップします。非表示にすると能力を失います。同様に、フォーカス可能にしてフォーカスを与えると、テキスト コンポーネントからキャレットがプルされます。

于 2012-01-31T02:45:11.350 に答える
0

フィールド current_active を追加し、メソッド actionPerformed で簡単なチェックを行います。完璧ではありませんが、シンプルなアプリの場合、これでうまくいくと思います。あなたの2つの要件を解決する大雑把な方法。:-) それがあなたにとってもうまくいくことを願っています。

import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class WaitCursor extends JFrame
{
    private static boolean current_active = false;

    public WaitCursor()
    {
        setResizable(false);

        setName(getClass().getSimpleName());
        setTitle("My Frame");
        setSize(300, 300);

        getContentPane().add(new MyButtonPanel());
    }

    private class MyButtonPanel extends JPanel
    {

        public MyButtonPanel()
        {
            JButton btnStart = new JButton("Start");
            btnStart.addActionListener(new BtnStartActionListener());
            add(btnStart);
        }

        private class BtnStartActionListener implements ActionListener
        {



            // change to wait_cursor
            public void actionPerformed(ActionEvent e)
            {
                if (!current_active)
                {
                    Component root = SwingUtilities.getRoot((JButton) e.getSource());
                    JOptionPane.showMessageDialog(root, "Wait 10 seconds");
                    root.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

                    // TODO: Disabling the root component prevents the WAIT_CURSOR from being displayed
                    //root.setEnabled(false);
                    current_active = true;
                    new Thread(new TimeKiller(root)).start();   

                }
            }
        }   
    }

    private class TimeKiller implements Runnable
    {
        Component m_root;

        public TimeKiller(Component p_root)
        {
            m_root = p_root;

        }       

        @Override
        public void run()
        {
            try
            {
                Thread.sleep(10 * 1000);                
            }
            catch (InterruptedException e)
            {
                //Ignore it
            }
            // Change back to DEFAULT CURSOR
            JOptionPane.showMessageDialog(m_root, "Done waiting");
            m_root.setCursor(Cursor.getDefaultCursor());
            current_active = false;
        }

    }

    // create and setup the window.
    public static void createAndShowGUI() 
    {
        WaitCursor frame = new WaitCursor();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    createAndShowGUI();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    System.exit(0);
                }
            }
        });
    }

}
于 2012-01-31T09:50:01.367 に答える