如何在 Eclipse 向导中正确更新持续时间未知的操作的进度条?

发布于 2024-12-07 22:47:30 字数 1595 浏览 1 评论 0原文

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

I have implemented a wizard for my Eclipse plug-in, showing several pages. One of these pages needs some lengthy initialization, that means it consists of a SWT table, which needs to be populated by information coming from an external source. This source needs to be activated first (one single method call that returns after a couple of seconds - I can not know in advance how long it will take exactly), before it can be used as input for for the table viewer. This initialization is currently done by the table model provider when it needs to access the external source for the first time.

Therefore, when I enter the wizard page, I would like to show a dummy progress bar that just counts up for a while. My approach was the following, but unfortunately does not work at all:

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);
    }
}

This method gets then invoked when the wizard page's setVisible()-method is called and should, after a couple of seconds, set the viewer's input. This, however, never happens, because the inner-most run()-method never gets executed.

Any hints on how to deal with long-running (where an exact estimate is not available) initializations in Eclipse wizards would be very appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ゝ杯具 2024-12-14 22:47:30

我在下面给出了一个关于如何使用 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();
}

希望这有帮助!

I have given below a simple example on how to use IRunnableWithProgress along with a ProgressMonitorDialog to perform a task of unknown quantity. To start with, have an implementation to IRunnableWithProgress from where the actual task is performed. This implementation could be an inner class.

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();
    }
}

Now, a generic implementation to ProgressMonitorDialog can be created as below which could be used for other places where a progress monitor dialog is required.

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;
    }
}

Having got the required implementation, the task can be invoked as below to get it processed with a progress dialog.

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();
}

Hope this helps!

感性不性感 2024-12-14 22:47:30

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

I assume the reason why it's "not working" for you is that the preparation of input is done in UI thread meaning that the progress bar cannot be updated. A better approach is to prepare input in advance and only set input to viewer after that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文