我制作了一个不时设置按钮setEnable
的程序。 Thread.sleep()
在另一个班级。这是代码:
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);
}
}
然而,当我把它放在课堂上的actionListener
时:
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);
}
}
它冻结了我的整个程序,基于这个例子,我已经知道线程睡眠应该在另一个线程中运行,以阻止当前类冻结。但我期望新的thread.sleep仍然冻结其操作,就像它仍然会执行上面的代码,但按钮将响应,因为它在另一个线程。但令人惊讶的是它完成了我想要它做的事情,并没有像第一个程序那样立即将所有内容设置为禁用。
答案 0 :(得分:3)
Thread.sleep()
使当前线程暂停。您正在actionPerformed
中运行它,即在Swing事件中。所有Swing操作都在一个线程EDT中完成。当您使用Thread.sleep()暂停它时,Swing无法处理任何其他事件,因为您尚未从actionPerformed侦听器返回。因此,GUI冻结(不是完整的应用程序,只是GUI)。
通常,由于这个原因,在Swing事件中执行长时间运行是不好的做法。对于你想要做的事情,最好的选择是使用Swing计时器。
答案 1 :(得分:2)
Thread.sleep
将导致执行调用的线程在指定时间内休眠(或直到线程被中断)。当您在actionPerformed
方法中调用它时,它会导致UI线程休眠。这就是你的程序锁定的原因。
你应该开始一个单独的线程,它会在你睡觉之间逐步完成你想要进行的各种调用。或者(在我看来更好)你可以使用Swing timers做你想做的事。
答案 2 :(得分:2)
正在发生的事情是,在第二个示例Thread.sleep
阻止EDT
,因此不会再发生UI更新。相反,在第一个示例中,您在分隔sleep
中调用Thread
,因此不会发生“冻结”。对于这样的任务,首选使用Swing Timers。