我有一个JButton,它在点击时执行一个动作。在actionPerformed我想在调用NotifyObserver之前更新按钮文本,NotifyObserver包含大量计算。问题是在完成NotifyObserver调用的所有操作之前,buttontext不会更新。这是JButton动作代码:
//Action for sinoButton
sinoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
sinoButton.setText("Loading Sinogram"); //Set text while loading sinogram
NotifyObserversSinogram(); //Notify observer and start sinogram calculation
}
});
如您所见,应在通知观察者之前更新按钮文本。关于如何解决这个问题的任何想法?
答案 0 :(得分:3)
修改强> 由于Swing不是线程安全的,你必须使用Swingutilities:
JButton b = new JButton("Run query");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Thread queryThread = new Thread() {
public void run() {
runQueries();
}
};
queryThread.start();
}
});
// Called from non-UI thread
private void runQueries() {
for (int i = 0; i < noQueries; i++) {
runDatabaseQuery(i);
updateProgress(i);
}
}
private void updateProgress(final int queryNo) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Here, we can safely update the GUI
// because we'll be called from the
// event dispatch thread
statusLabel.setText("Query: " + queryNo);
}
});
}
以下是一些有关其工作原理的更完整信息:Threading with swing
答案 1 :(得分:3)
如果NotifyObserversSinogram()
没有进行Swing特定计算,只需将其放在另一个线程中:
public void actionPerformed(ActionEvent e) {
sinoButton.setText("Loading Sinogram");
new Thread() {
public void run(){
NotifyObserversSinogram();
}
}.start();
}
如果是,请参阅SwingWorker
。
答案 2 :(得分:2)
Swing是一个单线程框架,ActionListener
在Event Dispatching Thread的上下文中执行,这将阻止UI在actionPerformed
方法存在之前被更新
现在,您可以使用另一个线程来运行计算,但Swing也不是线程安全的。
一个简单的解决方案是使用SwingWorker
,它可以让您安全地更新用户界面,提供进度更新,并在工作人员done
时通知
有关详细信息,请参阅Concurrency in Swing和Worker Threads and SwingWorker
答案 3 :(得分:0)
JButton sinoButton = new JButton();
//Action for sinoButton
sinoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
((JButton)e.getSource()).setText("Loading Sinogram"); //Set text while loading sinogram
/*Since this is time consuming operation running on EDT its causing the issue.
* To fix it run the time consuming operation in a thread other than EDT
* */
new Thread(){
public void run() {
NotifyObserversSinogram();
};
}.start();
}
});