【问题标题】:How can I correctly update a progress bar for an operation of unknown duration within an Eclipse wizard?如何在 Eclipse 向导中为未知持续时间的操作正确更新进度条?
【发布时间】:2011-11-29 23:08:30
【问题描述】:

我已经为我的 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 向导中处理长时间运行(无法获得准确估计)初始化的提示将不胜感激!

【问题讨论】:

  • 我看不出你的方法的价值。只要不知道会持续多久,给用户的反馈就是错误的。为什么不测量一段时间内整个操作的长度,然后决定每一步应该完成多少滴答声?当您以beginTask(String, int) 开头时,int 应该是整个跨度。请参阅IProgressMonitor API
  • 感谢您的评论。我的目标是向用户反馈正在发生的事情,而不仅仅是阻止 UI。外部源(实际上是基于文件的三重存储)的初始化只需要几秒钟(5-10),但无法真正测量/估计。它发生在单个框架方法中,并且在一定程度上取决于已存储的数据量。

标签: eclipse swt progress


【解决方案1】:

我在下面给出了一个简单的例子,说明如何使用IRunnableWithProgressProgressMonitorDialog 来执行未知数量的任务。首先,从执行实际任务的地方实现 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();
}

希望这会有所帮助!

【讨论】:

  • 谢谢,IProgressMonitor.UNKNOWN 肯定是一个好主意,但是,我会对如何处理案例感兴趣,其中 performRead(..) 将是一个(阻塞)框架方法不接受我可以调用工作()的监视器
【解决方案2】:

我认为它对您“不起作用”的原因是输入的准备工作是在 UI 线程中完成的,这意味着无法更新进度条。更好的方法是提前准备好输入,然后才将输入设置给查看器。

【讨论】:

  • 这很好——我会检查准备运行的线程。
猜你喜欢
  • 1970-01-01
  • 2010-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-27
相关资源
最近更新 更多