我正在努力:
这应该很简单,但我得到一个奇怪的错误: 第一个文本永远不会被写入,应用程序只等待2秒钟,然后显示最终文本。这是示例代码:
private void testButtonActionPerformed(java.awt.event.ActionEvent evt) {
displayLabel.setText("Clicked!");
// first method with System timer
/*
long t0= System.currentTimeMillis();
long t1= System.currentTimeMillis();
do{
t1 = System.currentTimeMillis();
}
while ((t1 - t0) < (2000));
*/
// second method with thread.sleep()
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {}
displayLabel.setText("STOP");
}
使用此代码,文本“Clicked!”永远不会显示。我只得到2秒 - 暂停,然后是“停止”文本。 我尝试使用循环或Thread.sleep()的系统计时器,但两种方法都给出相同的结果。
答案 0 :(得分:2)
仅提供有关Andrew Thompson评论的更多背景:EDT负责处理gui更新。如果您使用Thread.sleep(...)
阻止它们,那么这些更新也会被阻止。这就是为什么你没有看到第一个文本 - EDT无法在标签上进行更新。
答案 1 :(得分:2)
这是一个可运行的例子,可以完成你所追求的目标。正如Andrew Thompson的评论所述,SwingWorker
是解决这个问题的好方法。
基本原则是永远不会阻止Event Dispatch Thread。这是负责重新绘制GUI并响应用户交互的线程,所以如果你在EDT上做一些计算成本高昂的东西,你的GUI就会停止响应。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
public class ButtonTest {
public static void main(String[] args) {
// create a frame and a button
JFrame frame = new JFrame();
final JButton button = new JButton("Button");
frame.add(button);
// add an action listener to the button
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// change the button text right away
button.setText( "Clicked" );
// create a SwingWorker which simply waits 2000 milliseconds
// simulating a computation being performed
SwingWorker<String, Object> worker = new SwingWorker<String, Object>() {
@Override
public String doInBackground() {
// it's safe to call Thread.sleep( ) here
// doInBackground is executed on a separate worker
// thread
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
return "Done";
}
@Override
protected void done() {
// done() is executed back on the Swing thread
// so it's safe to updated the state of the button
try {
button.setText(get());
} catch (Exception e) { }
}
};
// run the worker
worker.execute();
}
});
frame.setSize( 300, 300 );
frame.setVisible( true );
}
}
答案 2 :(得分:2)
您正在搞乱事件调度程序线程。 这将导致您所看到的不期望的UI行为。如果您计划进行这些类型的动画,请务必阅读@Andrew Thompson建议的内容,并了解您是否可以阅读此内容 - Filthy rich clients
最好使用Swing Timer
,如下面的curde示例所示:( 是的,它很粗糙,我不担心停止计时器等):
public class DelayTest extends JPanel{
JLabel messageLabel = new JLabel();
JButton actionButton = new JButton("Click Me");
String[] messages = {"Clicked", "Stop!"};
int i=0;
public DelayTest(){
super();
add(messageLabel);
add(actionButton);
actionButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Timer timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if(i<=1)
messageLabel.setText(messages[i++]);
}
});
timer.start();
}
});
}
}
修改强>
为什么不停止计时器:
@Override
public void actionPerformed(ActionEvent evt) {
if (i <= 1) {
messageLabel.setText(messages[i++]);
} else {
((Timer)evt.getSource()).stop();
}
}
});