Reputation: 13
I've made a program that sets a button's setEnable
from time to time. The Thread.sleep()
is in another class. Here's the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Try extends JFrame implements ActionListener{
JButton n1 = new JButton("1");
JButton n2 = new JButton("2");
JButton n3 = new JButton("3");
JButton show = new JButton("Show");
{
show.addActionListener(this);
n1.setEnabled(false);
n2.setEnabled(false);
n3.setEnabled(false);
}
public Try(){
super("Try");
setVisible(true);
setSize(500, 200);
setLayout(new GridLayout(1, 4));
add(n1);
add(n2);
add(n3);
add(show);
}
public void actionPerformed(ActionEvent a) {
Object clicked = a.getSource();
if(show == clicked){
new EasyLevel1().start();
}
}
class EasyLevel1 extends Thread {
public void run() {
try {
n1.setEnabled(true);
Thread.sleep(1000);
n1.setEnabled(false);
n2.setEnabled(true);
Thread.sleep(1000);
n2.setEnabled(false);
n3.setEnabled(true);
Thread.sleep(1000);
n3.setEnabled(false);
} catch (InterruptedException e){
}
}
}
public static void main(String[] args){
Try frame = new Try();
frame.setVisible(true);
}
}
However, when I put it on my actionListener
within the class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Try extends JFrame implements ActionListener{
JButton n1 = new JButton("1");
JButton n2 = new JButton("2");
JButton n3 = new JButton("3");
JButton show = new JButton("Show");
{
show.addActionListener(this);
n1.setEnabled(false);
n2.setEnabled(false);
n3.setEnabled(false);
}
public Try(){
super("Try");
setVisible(true);
setSize(500, 200);
setLayout(new GridLayout(1, 4));
add(n1);
add(n2);
add(n3);
add(show);
}
public void actionPerformed(ActionEvent a) {
Object clicked = a.getSource();
if(show == clicked){
try {n1.setEnabled(true);
Thread.sleep(1000);
n1.setEnabled(false);
n2.setEnabled(true);
Thread.sleep(1000);
n2.setEnabled(false);
n3.setEnabled(true);
Thread.sleep(1000);
n3.setEnabled(false);
} catch (InterruptedException e){}
}
}
public static void main(String[] args){
Try frame = new Try();
frame.setVisible(true);
}
}
It freezes my whole program, based from that example I've understood that a thread sleep should be ran in another thread to stop the current class from freezing. But I expected the new thread.sleep with still freeze its operations like it will still do the code above but the buttons will be responsive since its in another thread. But surprisingly it did what I wanted it to do, It didn't instantly set everything to disabled like the first program.
Upvotes: 1
Views: 4233
Reputation: 159844
What is happening is that in the 2nd example Thread.sleep
is blocking the EDT
so no further UI updates occur. In contrast, in the first example you are calling sleep
in a separare Thread
so no "freezing" occurs. For tasks like this the use of Swing Timers is preferred.
Upvotes: 2
Reputation: 234847
Thread.sleep
will cause the thread that executes the call to sleep for the specified time (or until the thread is interrupted). When you call it in the actionPerformed
method, it causes the UI thread to sleep. That's why your program is locking up.
You should start a separate thread that will step through the various calls you want to make while sleeping in between. Alternatively (and much better, in my opinion) you could use Swing timers to do what you want.
Upvotes: 2
Reputation: 15533
Thread.sleep()
makes the current thread pause. You are running it in an actionPerformed
, that is in a Swing Event. All Swing operations are done in a single thread, the EDT. When you pause it with a Thread.sleep(), Swing can not handle any other event because you haven't returned from the actionPerformed listener. Therefore, the GUI freezes (not the complete application, just the GUI).
In general, it is bad practice to do long-running actions in a Swing event because of this. For what you are trying to do, the good alternative is to use Swing timers.
Upvotes: 3