Wait for cursor and disable Java application

I want the user to click a button to start a background thread.

While the thread is processing, I want two things to happen:

1) WAIT_CURSOR should be displayed.

2) The application should not respond to mouse events.

According to setCursor documentation "This cursor image is displayed when the contains method for this component returns true for the current cursor location, and this Component is displayed, displayed, and available."

I want my application to be disabled while this background thread is processing.

Any ideas on how to get the required functionality?

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
source share
3 answers

issue 065 from Javaspecialists.eu fully answers your question.

+5
source

One way to disable it is to use a glass panel to block mouse input.

For instance:

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

The glass panel will capture mouse events if it becomes visible and receives a MouseListener. He will lose his ability if he becomes invisible. In the same way, he will pull the carriage out of the text components if you make it focusable and give it focus.

+4
source

the current_active field is added and in the actionPerformed method do a simple check. Although not ideal, but for a simple application, I think this does the trick. A rough way to solve your two requirements. :-) I hope this works for you too.

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

Source: https://habr.com/ru/post/1393885/


All Articles