Java Thread.Sleep Puts Swing UI to Sleep Too

java thread.sleep puts swing ui to sleep too

You are correct about the code putting the UI to sleep. Since sleep is called on the Event Dispatch Thread (the thread responsible for running the gui) the UI stops processing events and 'goes to sleep'.

I think what you want is a javax.swing.Timer.

Timer t = new Timer(1000 * 5, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// do your reoccuring task
}
});

This will cause your reoccurring task to be performed off of the EDT, and thus it wont leave your ui unresponsive.

How to update UI when using Thread.sleep

Change the ActionListner so the sorting is done on a separate thread:

@Override
public void actionPerformed(ActionEvent arg0)
{
new Thread(()->bubbleSort(array)).start();
}

To update UI using Swing thread use : SwingUtilities.invokeLater(()->repaint()); instead of this.repaint();

Thread sleep in GUI Action Listener JAVA

Part of the issue is that you're calling Thread.sleep()

That is putting the Main thread to sleep so you're entire application stops executing.

 for(int i=600; i>0;
try{
Thread.sleep(1000);
String cc = ""+i;
lab1.setText(cc);
}

For your application sounds like you need to make a separate thread to run that will then wake up and actually run the alarm.

Maybe try something like this:

Thread t = new Thread(() -> {
for(int i=600; i>0;i-- ){
try{
Thread.sleep(1000);
String cc = ""+i;
lab1.setText(cc);
}
catch(InterruptedException e){
System.out.println("Chyba!");
}
}
});
t.start();

The call to Thread.sleep() should put the sub thread to sleep and not effect the rest of your application.

Please note I'm using arrow notation (->) for the thread. You don't have to. Instead you can simply create a runnable:

Runnable alarmRunnable = new Runnable() {
@Override
public void run() {
for(int i=600; i>0;i-- ){
try{
Thread.sleep(1000);
String cc = ""+i;
lab1.setText(cc);
}
catch(InterruptedException e){
System.out.println("Chyba!");
}
}
}
};

Thread t = new Thread(alarmRunnable);
t.start();

The arrow notation (otherwise known as lambda) I think is cleaner though.

Thread.sleep() starts before my JButton text changes (The animation is too long) How to prevent this?

By calling Thread.sleep on the Swing event thread, you are putting the entire GUI to sleep, meaning it cannot do any key actions of updating the GUI or interacting with the user until the sleep time is over. The solution is to never do this. If you need to have a time delay in a Swing GUI, there is a Swing tool created explicitly for this, a Swing Timer: Swing Timer Tutorial

The underlying mechanism is to give the timer a delay time in microseconds as its first constructor parameter, and give it a call back method as an ActionListener as its second parameter. Set it to non-repeating, and call .start() on it. The call-back should do the actions that you desire after the delay time has finished.

For example, something like:

public void oncardflipped(String card) {
if (twocardspicked) {
int delay = 1000;
Timer timer = new Timer(delay, e -> {
// the actionPerformed call-back code
pickedcardbuttons[0].setText("");
pickedcardbuttons[1].setText("");
});
timer.setRepeats(false);
timer.start();
}
}

Note that you should not use a java.util.Timer, the other main Java Timer class, since while this sort-of works, it is not Swing thread-safe.

How can I pause/sleep/wait in a java swing app?

Using Thread#sleep method in swing applications in main thread will cause the GUI to freeze (since the thread sleeps, events cannot take place). Thread#sleep method in swing applications is only allowed to be used only by SwingWorkers, and this in their #doInBackround method.

In order to wait in a swing application (or do something periodically), you will have to use a Swing Timer. Take a look at an example i have made:

import java.awt.FlowLayout;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer; //Note the import

public class TimerExample extends JFrame {
private static final int TIMER_DELAY = 1000;
private Timer timer;

public TimerExample () {
super();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 200);
setLocationRelativeTo(null);
getContentPane().setLayout(new FlowLayout());

timer = new Timer(TIMER_DELAY, e -> {
System.out.println("Current Time is: " + new Date(System.currentTimeMillis()));
});
//timer.setRepeats(false); //Do it once, or repeat it?
JButton button = new JButton("Start");
button.addActionListener(e -> timer.start());
getContentPane().add(button);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new TimerExample().setVisible(true));
}
}

Output after "Start" button is pressed:

Current Time is: Mon Feb 25 13:30:44 EET 2019

Current Time is: Mon Feb 25 13:30:45 EET 2019

Current Time is: Mon Feb 25 13:30:46 EET 2019

As you can see, Timer's action listener fires every second.

So in your case:

timer = new Timer(TIMER_DELAY, e -> {
if (currentIndexLabel != paint.length-1) {
upateLabels();
timer.restart(); //Do this check again after 1000ms
}
});
button.addActionListener(e -> timer.start());

Thread.Sleep() is freezing

Don't ever call Thread.sleep(...) from within the Swing event thread as this will put the event thread itself to sleep. Since this thread is responsible for all Swing painting and user interaction, this will put your application to sleep.

If all you want is a delay in the display, then consider use of a Swing Timer.

If on the other hand your event thread is being compromised by a long-running task, then do the task in the background, using a SwingWorker (as suggested by Guillaume 1+ to him).



Related Topics



Leave a reply



Submit