Подождите курсор и отключите Java-приложение

Я хочу, чтобы пользователь нажал кнопку, чтобы запустить фоновый поток.

Пока поток обрабатывается, я хочу, чтобы произошли две вещи:

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);
                }
            }
        });
    }

}

person bigleftie    schedule 31.01.2012    source источник


Ответы (2)


Один из способов отключить его - использовать стеклянную панель, чтобы заблокировать ввод с помощью мыши.

Например:

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. Он потеряет способность, если будет установлен невидимым. Точно так же он будет вытягивать курсор из текстовых компонентов, если вы сделаете его фокусируемым и поставите на него фокус.

person Hovercraft Full Of Eels    schedule 31.01.2012
comment
Использование glassPane.requestFocusInWindow () перемещает фокус в окно (и из любого текстового компонента, который мог его иметь), но этот подход не предотвращает активность клавиатуры в окне с WAIT_CURSOR. Используя клавишу TAB, пользователь мог перейти к любому текстовому полю в окне и ввести текст. Я использовал glassPane.addKeyListener (aDoNothingKeyListener), чтобы полностью заблокировать все действия игнорирования, когда отображается WAIT_CURSOR. - person bigleftie; 18.03.2012

добавил поле current_active и в методе actionPerformed выполните простую проверку. Хотя это не идеально, но для простого приложения я думаю, что это поможет. Грубый способ решения ваших двух требований. :-) Надеюсь, это сработает и для вас.

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);
                }
            }
        });
    }

}
person Jasonw    schedule 31.01.2012