我有一个JButton,它在点击时执行一个动作。在操作执行中,我想在调用包含大量计算的 NotifyObserver 之前更新按钮文本。问题是,在 NotifyObserver 调用的所有操作完成之前,按钮文本不会更新。以下是 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
}
});
如您所见,应在通知观察者之前更新按钮文本。关于如何解决这个问题的任何想法?
如果NotifyObserversSinogram()
不执行特定于 Swing 的计算,只需将其放在另一个线程中:
public void actionPerformed(ActionEvent e) {
sinoButton.setText("Loading Sinogram");
new Thread() {
public void run(){
NotifyObserversSinogram();
}
}.start();
}
如果是,请参阅SwingWorker
。
编辑由于 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);
}
});
}
这里有一些关于它如何工作的更完整的信息: 带摆动的螺纹
Swing 是一个单线程框架,ActionListener
在事件调度线程的上下文中执行,这将阻止 UI 更新,直到 actionPerformed
方法存在
现在,您可以使用另一个线程来运行计算,但 Swing 也不是线程安全的。
一个简单的解决方案是使用 SwingWorker
,它有办法安全地更新 UI,提供进度更新,并在工作人员done
时收到通知
有关更多详细信息,请参阅 Swing 和工作线程中的并发和 SwingWorker
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();
}
});