Подождите курсор и отключите Java-приложение - PullRequest
4 голосов
/ 31 января 2012

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

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

1) WAIT_CURSOR должен быть

2) Приложение не должно реагировать на события мыши.

Согласно документации setCursor"Это изображение курсора отображается, когда возвращается метод содержимого этого компонента.Значение 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);
                }
            }
        });
    }

}

Ответы [ 2 ]

4 голосов
/ 31 января 2012

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

Например:

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

0 голосов
/ 31 января 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);
                }
            }
        });
    }

}
...