我为Eclipse插件实现了一个向导,显示了几个页面。其中一个页面需要一些冗长的初始化,这意味着它由一个SWT表组成,需要由来自外部源的信息填充。需要首先激活此源(一个单一的方法调用,在几秒钟之后返回 - 我无法预先知道它将需要多长时间),然后才能将其用作表查看器的输入。当初始化需要首次访问外部源时,表初始化由表模型提供程序完成。
因此,当我进入向导页面时,我想显示一个虚拟进度条,它只会计算一段时间。我的方法如下,但遗憾的是根本不起作用:
private void initViewer() {
IRunnableWithProgress runnable = new IRunnableWithProgress() { // needed to embed long running operation into the wizard page
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
SubMonitor progress = SubMonitor.convert(monitor);
Thread thread = new Thread() {
@Override
public void run() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
viewer.setInput(ResourcesPlugin.getWorkspace().getRoot()); // this will make the table provider initialize the external source.
}
});
}
};
thread.start();
while(thread.isAlive()) {
progress.setWorkRemaining(10000);
progress.worked(1);
}
progress.done();
}
};
try {
getContainer().run(false, false, runnable);
} catch(Exception e) {
throw new Exception("Could not access data store", e);
}
}
当调用向导页面的setVisible() - 方法时,会调用此方法,并在几秒钟后设置查看器的输入。但是,这绝不会发生,因为最内部的run() - 方法永远不会被执行。
有关如何处理长期运行(无法获得准确估计值)的任何提示,我们将非常感谢Eclipse向导中的初始化!
答案 0 :(得分:1)
我认为它“无法正常工作”的原因是输入的准备是在UI线程中完成的,这意味着无法更新进度条。更好的方法是提前准备输入,然后在此之后仅向观众设置输入。
答案 1 :(得分:1)
我在下面给出了一个简单的示例,说明如何使用IRunnableWithProgress和ProgressMonitorDialog执行未知数量的任务。首先,从执行实际任务的地方获得IRunnableWithProgress的实现。这个实现可能是一个内部类。
public class MyRunnableWithProgress implements IRunnableWithProgress {
private String _fileName;
public MyRunnableWithProgress(String fileName) {
_fileName = fileName;
}
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
int totalUnitsOfWork = IProgressMonitor.UNKNOWN;
monitor.beginTask("Performing read. Please wait...", totalUnitsOfWork);
performRead(_fileName, monitor); // This only performs the tasks
monitor.done();
}
}
现在,可以创建 ProgressMonitorDialog 的通用实现,如下所示,可以用于需要进度监视器对话框的其他地方。
public class MyProgressMonitorDialog extends ProgressMonitorDialog {
private boolean cancellable;
public MyProgressMonitorDialog(Shell parent, boolean cancellable) {
super(parent);
this.cancellable = cancellable;
}
@Override
public Composite createDialogArea(Composite parent) {
Composite container = (Composite) super.createDialogArea(parent);
setCancelable(cancellable);
return container;
}
}
获得所需的实现后,可以按如下方式调用该任务,以使用进度对话框处理该任务。
boolean cancellable = false;
IRunnableWithProgress myRunnable = new MyRunnableWithProgress(receivedFileName);
ProgressMonitorDialog progressMonitorDialog = new MyProgressMonitorDialog(getShell(), cancellable);
try {
progressMonitorDialog.run(true, true, myRunnable);
} catch (InvocationTargetException e) {
// Catch in your best way
throw new RuntimeException(e);
} catch (InterruptedException e) {
//Catch in your best way
Thread.currentThread().interrupt();
}
希望这有帮助!