How to Pause/Sleep/Wait in a Java Swing App

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

How to delay an answer while not freezing the thread?

Consider using a Timer to prevent main thread from freezing :

import javax.swing.*;
import java.awt.event.*;

ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent evt) {

}
};
Timer countdown = new Timer(1000 ,task);
countdown.setRepeats(false);
countdown.start();

where 1000 is the delay time in milliseconds and inside the actionPerformed function is where your code executes after the delay time set.

Java GUI, need to pause a method without freezing GUI aswell

You can't do it without creating a separate thread. Creating a thread in Java is easy. The only thing to pay attention to is that you can only touch the UI through the main thread. For this reason you need to use something like SwingUtilities.invokeLater().

Java: How to wait 1 second in a GUI

You shouldn't call the sleep() method inside your gui thread, otherwise all your interface will freeze. You should use a separate thread instead and communicate with your gui thread to tell him when to update the interface.

The best way to work with threads in a Swing application is using the SwingWorker object. In particular, it offer two hook methods that are process and done that are called directly in your gui thread and are a powerful way to publish progress done by your worker thread. In your case, you should do something like that:

SwingWorker<Void, String> worker = new SwingWorker<Void, String>(){

@Override
protected Void doInBackground() throws Exception {
this.publish("Everything");
Thread.sleep(1000);
this.publish("Everything is");
Thread.sleep(1000);
this.publish("Everything is Awesome!");
return null;
}

@Override
protected void process(List<String> res){
for(String text : res){
label.setText(text);
}
}

};

worker.execute();

P.S.: you can call the execute() method only once on a worker object. If you want to call it multiple times you have to instantiate new objects.

Trying to pause program execution within an if statement (Swing)

That is because swing timer is asynchronous. So you have to put second line of your code (and all following logic) into action listener like:

mPlayerLastRollLabel.setText("Player rolled: ...");
Timer t = new Timer(5000, new ActionListener(){
public void actionPerformed(ActionEvent ae){
mPlayerLastRollLabel.setText("Player rolled: " + mFaceNumber);
}
});
t.setRepeats(false);
t.start();

Or you can put second half after sleep into separate function and call it from actionPerfomed method. Doing it this way instead of Thread.sleep you release graphical thread (which is one for all UI) until your sleeping time is up. If don't release graphical thread then your UI would freeze because there would be no thread to react to user actions.

How do I pause Java Simulation using Swing

You need to provide additional logic to your simulation thread that will accept "signals" from controlling (GUI) thread and wait for the next controlling signal to resume execution.

For example you can use volatile boolean isPaused instance field in simulation thread. Set it to true/false to pause/resume simulation thread. In simulation thread implement corresponding logic:

public void run() {
while (true) {
simulate();
while (isPaused) {
Thread.sleep(100);
}
}
}


Related Topics



Leave a reply



Submit