我正在更新EDT之外的Swing组件吗?
我一直在阅读Swing,线程,invokeLater(),SwingWorker等等,但我似乎无法让我的头脑全面,所以我试图创建一个非常简单的程序来说明。 我看了很多例子,但是他们没有一个能够显示我正在尝试做什么。 我用Java编程已经很长时间了(自从我在2003年就读AP计算机科学以来,我真的没有用Java做过任何事情),所以请和我一起。
这就是我在我的例子中想要做的。 我有一个按钮和一个标签,当我点击按钮时,我想让程序暂停3秒钟,然后在标签的文本上附加一段时间。 在那3秒内,我希望GUI正常显示,并继续响应其他点击。 这是我写的:
import javax.swing.SwingWorker;
public class NewJFrame extends javax.swing.JFrame
{
private javax.swing.JButton jButton1;
private javax.swing.JLabel jLabel1;
public NewJFrame()
{
initComponents();
}
private void initComponents()
{
jButton1 = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jButton1.setText("Button");
jButton1.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
jButton1ActionPerformed(evt);
}
});
getContentPane().add(jButton1, java.awt.BorderLayout.CENTER);
jLabel1.setText("Text");
getContentPane().add(jLabel1, java.awt.BorderLayout.PAGE_END);
pack();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
SwingWorker worker=new SwingWorker()
{
protected Object doInBackground()
{
try{Thread.sleep(3000);}
catch (InterruptedException ex){}
return null;
}
};
worker.execute();
jLabel1.setText(jLabel1.getText()+".");
}
public static void main(String args[])
{
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run(){ new NewJFrame().setVisible(true); }
});
}
}
使用此代码,如果单击该按钮,则该句点会立即附加到标签上,这对我来说很有意义,因为我正在创建和休眠后台线程,并且让EDT可用来立即更新标签。 所以我试过这个:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
Thread thread = new Thread();
try{ thread.sleep(3000);}
catch (InterruptedException ex){}
jLabel1.setText(jLabel1.getText()+".");
}
这几乎可以工作,只是它会阻止EDT,导致按钮在连续三秒后变为蓝色,然后再将句号附加到标签的文本。 我不希望按钮看起来像是被按下了整整三秒,当它真的只是快速点击,所以我尝试了这一点:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
SwingWorker worker=new SwingWorker()
{
protected Object doInBackground()
{
try{Thread.sleep(3000);}
catch (InterruptedException ex){}
jLabel1.setText(jLabel1.getText()+".");
return null;
}
};
worker.execute();
}
这似乎工作,但不是我从后台线程调用jLabel1.setText(...)而不是EDT,因此打破了“Swing单线程规则?”。 如果是这样,是否有更好的方法来达到预期的效果? 如果不是,你能解释一下为什么?
你真的很接近...
试试像这样的东西。
SwingWorker worker=new SwingWorker()
{
protected Object doInBackground()
{
try{
Thread.sleep(3000);
}catch (InterruptedException ex){}
return null;
}
// This is executed within the context of the EDT AFTER the worker has completed...
public void done() {
jLabel1.setText(jLabel1.getText()+".");
}
};
worker.execute();
您可以通过使用EventQueue.isDispatchingThread()
来检查您是否在美国东部时间运行。
更新
你也可以使用javax.swing.Timer
,它可能更简单...
Timer timer = new Timer(3000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jLabel1.setText(jLabel1.getText()+".");
}
});
timer.setRepeats(false);
timer.start();
链接地址: http://www.djcxy.com/p/69611.html