[英]How to call SwingWorker .get() without freezing GUI?
我提供了一个样本来阐明问题:
public class Worker extends SwingWorker<Integer, Integer> {
private GeneralUserInterface gui;
public Worker(GeneralUserInterface gui){
this.gui = gui;
}
@Override
protected Integer doInBackground() throws Exception {
int someResultToReturn = 10;
for(int i=0; i<100; i++){
Thread.sleep(50);//The Work
publish(i+1);//calls process, which updates GUI
}
return someResultToReturn;
}
@Override
protected void process(List<Integer> values) {
for (Integer val : values) {
gui.updateProgressBar(val);
}
}
}
private void jButtonDoWorkActionPerformed(java.awt.event.ActionEvent evt) {
Worker worker = new Worker(this);
worker.execute();
try {
int resultToGet = worker.get();//Obviously freezes the GUI
} catch (InterruptedException | ExecutionException ex) {}
//NEXT LINE NEEDS THE RESULT TO CONTINUE
}
public void updateProgressBar(int value){
this.jProgressBar1.setValue(value);
}
如您所料,对worker.get()的调用使UI无响应,这是正常的,因为它等待线程完成。 通常如何解决这种问题?
通常如何解决这种问题?
通常,您要做的是重写Swingworker.done()
方法。 后台线程完成后,在GUI线程中执行完成。 然后,您可以安全地调用get而不会阻塞,并做您需要做的任何事情。
这是执行此操作的一种方法:
public class Worker extends SwingWorker<Integer, Integer> {
private GeneralUserInterface gui;
// omitted...
@Override
protected Integer doInBackground() throws Exception {
int someResultToReturn = 10;
for(int i=0; i<100; i++){
Thread.sleep(50);//The Work
publish(i+1);//calls process, which updates GUI
}
return someResultToReturn;
}
// omitted...
@Override
protected void done() {
try {
int resultToGet = worker.get();//Obviously freezes the GUI
} catch (InterruptedException | ExecutionException ex) {}
//NEXT LINE NEEDS THE RESULT TO CONTINUE
}
}
private void jButtonDoWorkActionPerformed(java.awt.event.ActionEvent evt) {
Worker worker = new Worker(this);
worker.execute();
}
但是,这可能不是最方便的设计。 我发现最好让GUI成为公共类,然后将swing worker创建为非静态内部类。 这样,“完成”方法可以轻松访问所有GUI私有变量。
更好的解决方案是为SwingWorker提供由GUI实现的接口的实例。 这样,您就可以让工作人员更新GUI。
public class GUI implements GUI_INTERFACE{
....
new foo(this);
@Override
public void INTERFACE_METHOD(Object info){
//Update Gui variables here.
}
}
对于您的SwingWorker:
class foo extends SwingWorker{
GUI_INTERFACE int
public foo(GUI_INTERFACE bar){
int=bar
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.