我有一个Java 8 Swing应用程序,当用户单击一个新按钮时,需要向它添加一个耗时的操作。我认为这是SwingWorker
的完美用例,尽管我以前从未写过。
[当用户单击按钮时,应用程序必须从几个不同的来源收集信息,然后启动此后台操作。它将计算一个InputAnalysis
,然后将该InputAnalysis
返回给EDT中的单击处理程序以更新UI。在运行时,我还希望它也更新JProgressBar
,以便用户看到正在取得的进展。迄今为止我最大的尝试:
// Button click handler (living in the EDT) that invokes the worker on button click:
analyzeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Fizz fizz = fizzService.fetchFromWs(1234);
Analyzer analyzer = new Analyzer(progressBar, nameTextField.getText(), fizz);
analyzer.execute();
// but now, how do I obtain the InputAnalysis instance?!
InputAnalysis analysis = null; // analyzer.getSomehow();
// now update the rest of the UI based on this analysis's properties
}
}
// New SwingWorker
public class Analyzer extends SwingWorker<InputAnalysis,Integer> {
private JProgressBar progressBar;
private String name;
private Fizz fizz;
// ctor omitted for brevity
@Override
protected void process(List<Integer> chunks) {
progressBar.setValue(chunks.size() - 1);
}
@Override
protected InputAnalysis doInBackground() {
// do a bunch of stuff
// 10% done
publish(10);
// do more stuff
// 50% done
publish(50);
// do final stuff
// 100% done
publish(100);
return new InputAnalysis(...);
}
}
我思考我正在正确更新progressBar
(如果不是,请纠正我!),但我不知道如何将InputAnalysis
送回EDT。 / click处理程序,以便我可以使用它更新UI。 有什么想法我要去哪里?
不是
progressBar.setValue(chunks.size() - 1);
由于集合的大小不是您想要的。相反,您希望显示集合的值:
for (int item : chucks) {
progressBar.setValue(item);
}
您还需要在其工作人员完成工作时在其get()
方法中或在该工作人员的状态值为done()
时通知您的PropertyChangeListener中调用SwingWorker.StateValue.DONE
相同的get()
调用将在EDT上返回新的InputAnalysis
对象,如果在工作进程运行期间发生任何异常,则将引发异常,因此您可以在那里处理它们。