I have a desktop application in which I am showing one Frame as notification but I want to stop that thread when mouse hover to the notification frame. Then how could I can do that?
Here current code:
final Notification not = new Notification();
Notification.notification_name.setText(msg[1]);
final ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();
s.schedule(new Runnable() {
public void run() {
not.setVisible(false); //should be invoked on the EDT
not.dispose();
}
}, 6, TimeUnit.SECONDS);
It's showing and Exit in 6 sec.
The code that I am trying.
final Notification not = new Notification();
not.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
try {
super.mouseEntered(e);
System.out.println("Mouse Entered");
//s.wait();
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
} catch (Exception x) {
x.printStackTrace();
}
}
#Override
public void mouseExited(MouseEvent e) {
try {
super.mouseExited(e);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
final ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();
s.schedule(new Runnable() {
public void run() {
not.setVisible(false); //should be invoked on the EDT
not.dispose();
}
}, 6, TimeUnit.SECONDS);
In this code Notification frame is showing till 6 sec but if user hover that frame then it should be Show till user mouse exit from that Frame.
Whenever you deal with anything that might affect the UI in some way, you need to be careful and ensure that everything is done within the context of the EDT.
javax.swing.Timer allows you to setup a callback at some time in the future that when triggered, will be called within the context of the EDT
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class TimeExample {
public static void main(String[] args) {
new TimeExample();
}
public TimeExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(new TestPane());
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Timer timer;
public TestPane() {
setBorder(new LineBorder(Color.BLACK));
timer = new Timer(6000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setBackground(Color.RED);
}
});
timer.setRepeats(false);
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
if (timer.isRunning()) {
timer.stop();
setBackground(Color.BLUE);
}
}
#Override
public void mouseExited(MouseEvent e) {
if (!timer.isRunning()) {
timer.restart();
setBackground(UIManager.getColor("Panel.background"));
}
}
/**
* Testing purposes only!!
*
* #param e
*/
#Override
public void mouseClicked(MouseEvent e) {
setBackground(UIManager.getColor("Panel.background"));
timer.restart();
}
};
addMouseListener(ma);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
}
}
Have a look at How to Use Swing Timers for more details
Related
I am trying to capture the moment a user finished resizing a JFrame through the mouse drag of a frame corner. I have so far found the below options, but they both print BLAH again and again until I am done stretching the window size. I only want it to print BLAH once I released the mouse after the continuous dragging of the JFrame corner resizing it. Any thoughts?
frame.addComponentListener(new ComponentAdapter()
{
public void componentResized(ComponentEvent evt) {
Component c = (Component)evt.getSource();
System.out.println("BLAH");
}
});
AND
frame.addComponentListener(new ComponentListener() {
#Override
public void componentShown(ComponentEvent e) {
// TODO Auto-generated method stub
}
#Override
public void componentResized(ComponentEvent e) {
// TODO Auto-generated method stub
System.out.println("BLAH");
}
#Override
public void componentMoved(ComponentEvent e) {
// TODO Auto-generated method stub
}
#Override
public void componentHidden(ComponentEvent e) {
// TODO Auto-generated method stub
}
}
);
The core problem is, you're unlikely to be able to detect when a mouse event occurs on the frame decorations, as it tends to be handled at a much lower level.
One trick I've used in the past, is to use a short lived, single run, Swing Timer, which is restarted each time componentResized is called. This means that the Timer will only trigger AFTER a "short delay" after componentResized stops been called, for example
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel label;
private Timer resizeTimer;
public TestPane() {
setLayout(new GridBagLayout());
label = new JLabel(".......");
add(label);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
if (resizeTimer == null) {
resizeTimer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText(getSize().width + "x" + getSize().getHeight());
resizeTimer.stop();
resizeTimer = null;
}
});
resizeTimer.setRepeats(false);
}
resizeTimer.restart();
}
});
}
}
}
I want to change the color of JTextField to red after typing something in it, and then after a second return to a default white background. I tried this outside the listener, and it worked, but when it comes to being a part of a listener, it doesn't (it just skips setting the red color). This is weird for me..
public class Test {
JFrame frame;
JTextField field;
public Test() {
frame = new JFrame();
field = new JTextField("A");
field.addKeyListener(new KeyBListener());
frame.getContentPane().add(field);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) { new Test(); }
private class KeyBListener implements KeyListener {
#Override
public void keyTyped(KeyEvent e) {
try {
field.setBackground(Color.RED);
Thread.sleep(1000);
field.setBackground(Color.WHITE);
} catch (InterruptedException es) { es.printStackTrace(); }
}
#Override
public void keyPressed(KeyEvent e) { }
#Override
public void keyReleased(KeyEvent e) { }
}
}
Try creating a separate Thread that listens to color change on the JTextField then changes it back. In this case at least you will not block the main Thread, although I'm not sure it's the most efficient way.
public Main() {
frame = new JFrame();
frame.setSize(800, 600);
field = new JTextField("A");
field.addKeyListener(new KeyBListener());
frame.getContentPane().add(field);
frame.pack();
frame.setVisible(true);
new Thread(() -> {
while(true) {
if(field.getBackground().equals(Color.RED))
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
field.setBackground(Color.WHITE);
}
}).start();
}
Your previous solution was working because it was executed from the AWT itself.
The keyTyped() method is executed on the Event dispatch thead (EDT), so you have to move the painting actions back to the AWT.
Have a look on SwingUtilities.invokeLater() (non-blocking) or SwingUtilities.invokeAndWait() (blocking), see
Oracle Doc
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
field.setBackground(Color.RED);
Thread.sleep(1000);
field.setBackground(Color.WHITE);
} catch (InterruptedException es) {
es.printStackTrace();
}
}
});
You can spawn a different thread in which you do the color manipulation. That ensures that the color manipulation is not happening inside EDT.
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class Test {
JFrame frame;
JTextField field;
AtomicBoolean isColorChangeOn = new AtomicBoolean();
public Test() {
frame = new JFrame();
field = new JTextField("A");
field.addKeyListener(new KeyBListener());
frame.getContentPane().add(field);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
isColorChangeOn.set(false);
}
public static void main(String[] args) {
new Test();
}
private class KeyBListener implements KeyListener {
#Override
public void keyTyped(KeyEvent e) {
if(!isColorChangeOn.get()) {
isColorChangeOn.set(true);
Runnable setcolor = ()->{
try {
System.out.println("color changing");
field.setBackground(Color.RED);
Thread.sleep(1000);
field.setBackground(Color.WHITE);
isColorChangeOn.set(false);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
};
new Thread(setcolor).start();
}
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
}
I'm trying to check a JFormattedTextField after a value has been entered to make sure it does not match any other values entered in the other similar fields. It becomes a real pain if this check happens repeatedly while the user is typing because I want to provide an error message and I need to implement a number of changes if the value changes. But inputs like 123 will match 12 before the 3 is typed even though no error has really been made yet. Thus the need for a delay. So I'm trying to use a document listener but delay it until the user has validated (as accepted by the text field, by action or shifting focus) the entry.
I thought I had a good method, and it nearly works. My plan was to use a document listener to set up focus and action listeners. Unfortunately, I seem to end up with tons of focus and action listeners since the document listener keeps adding them. That means the error message and subsequent processing happen a ridiculous number of times instead of once. I've tried two work-arounds: 1) remove focus and action listeners before adding new ones, and 2) use a boolean to mark the existence of the focus and action listeners to avoid creating them again.
sscce (I'm new here, should I leave out all the includes?):
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Tester {
private JFrame frame;
private JTextField textField;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Tester window = new Tester();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Tester() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(50, 50, 200, 50);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textField = new JTextField("Change this.");
textField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
trigger();
}
public void removeUpdate(DocumentEvent e) {
trigger();
}
public void changedUpdate(DocumentEvent e) {
trigger();
}
public void trigger() {
textField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField.getText());
}
});
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField.getText());
}
});
}
});
frame.add(textField);
}
}
So attempted fix 1 was to place textField.removeFocusListener(null) and textField.removeActionListener(null) just before the two textField.add... lines. Nothing changed from attempted fix 1. Attempted fix 2 was to create a boolean triggeringEvent outside of trigger() and then start trigger() with if(triggeringEvent == false) { triggeringEvent = true; ... all the focus and action listener lines. Attempted fix 2 just left me with nothing triggering at all.
Thank you for any insight anyone can provide!!!
Edit: I had tried Boann's addChangeListener, but that triggers incessantly, too, and it even triggers when the value hasn't been changed.
Edit: I thought I found a solution by adjusting attempted fix 2, but it fails with more than one JTextField:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Tester {
private JFrame frame;
private JTextField textField;
private boolean eventTrigger = false;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Tester window = new Tester();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Tester() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(50, 50, 200, 50);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textField = new JTextField("Change this.");
textField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void removeUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void changedUpdate(DocumentEvent e) {
}
public void trigger() {
eventTrigger = true;
textField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField.getText());
eventTrigger = false;
}
});
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField.getText());
eventTrigger = false;
}
});
}
});
frame.add(textField);
}
}
You can see in this. If you start hopping between fields there are a whole bunch of extra times it triggers. It works fine for the first one you try adjusting, but then it fails.
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Tester {
private JFrame frame;
private JPanel panel;
private JTextField textField1;
private JTextField textField2;
private boolean eventTrigger = false;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Tester window = new Tester();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Tester() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(50, 50, 200, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(new GridLayout(0,1,0,0));
textField1 = new JTextField("Change the first.");
textField2 = new JTextField("Change the second.");
textField1.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void removeUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void changedUpdate(DocumentEvent e) {
}
public void trigger() {
eventTrigger = true;
textField1.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField1.getText());
eventTrigger = false;
}
});
textField1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField1.getText());
eventTrigger = false;
}
});
}
});
textField2.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void removeUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void changedUpdate(DocumentEvent e) {
}
public void trigger() {
eventTrigger = true;
textField2.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField2.getText());
eventTrigger = false;
}
});
textField2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField2.getText());
eventTrigger = false;
}
});
}
});
panel.add(textField1);
panel.add(textField2);
frame.add(panel);
}
}
How would I go about closing a JFrame after user inactivity?
So far I have,
Thread.sleep(10000);
I would greatly appreciate it if someone could give me code to do this?
I am new to Java and want to know more about system security
This is an example of Braj's idea using a javax.swing.Timer.
It simplifies the process, as you don't need to monitor the time between events and ensures that when the timer is triggered, the event occurs within the Event Dispatching Thread, further reducing the complexity.
Also note that I included the AWTEvent.MOUSE_MOTION_EVENT_MASK and AWTEvent.MOUSE_WHEEL_EVENT_MASK events for good measure ;)
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AutoClose {
public static void main(String[] args) {
new AutoClose();
}
private Timer timer;
private JLabel label;
private JFrame frame;
public AutoClose() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
label = new JLabel("Waiting...");
frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(label);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
private int count;
#Override
public void eventDispatched(AWTEvent event) {
Object source = event.getSource();
if (source instanceof Component) {
Component comp = (Component) source;
Window win = null;
if (comp instanceof Window) {
win = (Window) comp;
} else {
win = SwingUtilities.windowForComponent(comp);
}
if (win == frame) {
timer.restart();
label.setText("Interrupted..." + (++count));
}
}
}
}, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_WHEEL_EVENT_MASK);
timer = new Timer(5000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
}
});
// You could use a WindowListener to start this
timer.start();
}
});
}
}
Try this one
Steps to follow:
Its listening for key event as well as mouse event.
A new thread is started that will check.
If the time difference is more than specified time (10 sec in below sample code) then dispose the window.
That's all.
Here is the sample code:
private long time;
...
long eventMask = AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK;
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
public void eventDispatched(AWTEvent e) {
time = System.currentTimeMillis();
}
}, eventMask);
time = System.currentTimeMillis();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
if (System.currentTimeMillis() - time > 10000) {
widnow.dispose();
break;
}
}
}
}).start();
I want to have the user press a button to kick off a background thread.
While the thread is processing, I want two things to happen:
1) A WAIT_CURSOR should be displayed.
2) The application should not respond to mouse events.
As per the 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 visible, displayable, and enabled. ".
I want my application to be disabled while this background thread is processing.
Any ideas how to get the functionality I want?
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);
}
}
});
}
}
One way to disable it is to use the glass pane to block mouse input.
For example:
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 pane will trap mouse events if it set visible and given a MouseListener. It will lose t his ability if it is set invisible. Likewise it will pull the caret from text components if you make it focusable and give it focus.
added a field current_active and at method actionPerformed, do a simple check. Albeit it is not perfect but for simple app, i think this do the trick. A crude way of solving your two requirement. :-) Hope it 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);
}
}
});
}
}