【问题标题】:Wait cursor and disable java application等待光标并禁用 java 应用程序
【发布时间】:2022-01-20 04:10:27
【问题描述】:

我想让用户按下一个按钮来启动一个后台线程。

当线程正在处理时,我希望发生两件事:

1) 应显示 WAIT_CURSOR。

2) 应用程序不应响应鼠标事件。

根据setCursor documentation“当该组件的 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);
                }
            }
        });
    }

}

【问题讨论】:

    标签: java swing mouse-cursor glasspane busy-cursor


    【解决方案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,它将捕获鼠标事件。如果设置为隐形,它将失去他的能力。同样,如果您使其具有焦点并赋予它焦点,它将从文本组件中提取插入符号。

    【讨论】:

    • 使用 glassPane.requestFocusInWindow() 将焦点移动到窗口(以及可能拥有它的任何文本组件之外),但这种方法不会阻止具有 WAIT_CURSOR 的窗口中的键盘活动。使用 TAB 键,用户可以导航到窗口中的任何文本字段并输入文本。当显示 WAIT_CURSOR 时,我使用 glassPane.addKeyListener(aDoNothingKeyListener) 完全阻止所有忽略活动。
    【解决方案2】:

    添加了一个字段 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);
                    }
                }
            });
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-08
      • 1970-01-01
      • 1970-01-01
      • 2012-06-16
      • 2011-10-15
      相关资源
      最近更新 更多