[英]Am I updating Swing component outside of EDT?
我已經閱讀了很多有關Swing,線程,invokeLater(),SwingWorker等的內容,但是我似乎無法完全理解所有內容,因此我試圖創建一個非常簡單的程序來進行說明。 我看了很多示例,但是似乎都沒有顯示我正在嘗試做的事情。
這是我在示例中嘗試做的事情。 我有一個按鈕和一個標簽,當我單擊該按鈕時,我希望程序暫停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();
}
這似乎可行,但是我不是從后台線程而不是EDT調用jLabel1.setText(...),因此違反了“ 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()
查看是否在EDT中運行。
更新
您還可以使用javax.swing.Timer
,它可能會更容易...
Timer timer = new Timer(3000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jLabel1.setText(jLabel1.getText()+".");
}
});
timer.setRepeats(false);
timer.start();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.