You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在向导页点击Next后取消进度条时停留在当前页?

解决Eclipse向导中取消进度条后停留在原页面的问题

要实现点击Next时显示进度条,取消后停留在当前页面,核心是在向导切换页面的前置逻辑中处理进度任务,并根据取消结果决定是否切换页面。你之前在setVisible里处理进度的方式有问题——因为当setVisible(true)被调用时,页面已经开始切换了,此时取消无法阻止页面跳转。而你尝试的getNextPage方法是正确的方向,只是需要修正细节。

问题分析

  • 在WizardPage.setVisible中执行进度任务:页面已经处于切换流程中,取消后无法回退到原页面。
  • 原getNextPage代码中,进度任务没有正确处理取消后的中断抛出,导致框架无法感知取消操作。

正确实现方案

我们需要在主向导类的getNextPage方法中执行进度任务,利用该方法的返回值控制页面切换:如果任务被取消,返回null(停留在当前页);否则返回下一页。

1. 主向导类修改(核心逻辑)

public class TemplateCreationWizard extends Wizard implements INewWizard, IExecutableExtension {
    private InterfacePage interfacePage;
    private InterfaceDetailsPage interfaceDetailsPage;
    private ErrorPage error;
    private IConfigurationElement _configurationElement;
    private SelectedServerNode iServer;

    public TemplateCreationWizard() {
        setWindowTitle("Auto Development");
        setNeedsProgressMonitor(true); // 必须设置这个,让向导支持进度条
    }

    @Override
    public void addPages() {
        super.addPages();
        if (iServer.isConnected()) {
            interfacePage = new InterfacePage(iServer);
            interfaceDetailsPage = new InterfaceDetailsPage(iServer);
            addPage(interfacePage);
            addPage(interfaceDetailsPage);
        } else {
            error = new ErrorPage(iServer);
            addPage(error);
        }
    }

    @Override
    public boolean performFinish() {
        return true;
    }

    @Override
    public void init(IWorkbench workbench, IStructuredSelection selection) {
        // 保留原有初始化逻辑
        try {
            TreeSelection treeSelection = (TreeSelection) selection;
            TreePath[] treePaths = treeSelection.getPaths();
            if (null != treePaths && treePaths.length > 0) {
                TreePath treePath = treePaths[0];
                ISServerNode serverNode = (ISServerNode) treePath.getFirstSegment();
                ServerConnection iData = serverNode.getServerConnection();
                if (null != iData) {
                    iServer = createSelectedServerNode(iData);
                }
            } else {
                System.out.println("<empty selection>");
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
        _configurationElement = config;
    }

    @Override
    public IWizardPage getNextPage(final IWizardPage page) {
        // 只在从InterfacePage切换到下一页时处理进度
        if (!(page instanceof InterfacePage)) {
            return super.getNextPage(page);
        }

        try {
            // 运行进度任务,允许用户取消
            getContainer().run(true, true, new IRunnableWithProgress() {
                @Override
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                    monitor.beginTask("Fetching details from External System...", 10);
                    try {
                        for (int i = 0; i < 10; i++) {
                            if (monitor.isCanceled()) {
                                // 抛出InterruptedException,让外层捕获取消事件
                                throw new InterruptedException("Task cancelled by user");
                            }
                            monitor.worked(1);
                            Thread.sleep(2000);
                        }
                    } finally {
                        monitor.done();
                    }
                }
            });
        } catch (InvocationTargetException ex) {
            // 处理任务执行中的异常,比如外部系统调用失败
            ex.printStackTrace();
            // 可弹出错误提示,返回null停留在当前页
            return null;
        } catch (InterruptedException ex) {
            // 用户取消了进度任务,返回null停留在原页面
            return null;
        }

        // 任务正常完成,返回下一页
        return super.getNextPage(page);
    }
}

2. InterfacePage修改(确保canFlipToNextPage不触发进度)

public class InterfacePage extends WizardPage {
    private SelectedServerNode iServer = null;
    private Text interfaceId;

    protected InterfacePage(SelectedServerNode iServer) {
        super("InterfacePage");
        this.iServer = iServer;
        setTitle("Some title");
        setMessage("Some message");
    }

    @Override
    public void createControl(Composite parent) {
        // 保留原有UI创建逻辑
        Composite page = new Composite(parent, SWT.NONE);
        setControl(page);
        setPageComplete(false);
        GridLayout gridLayout = new GridLayout(2, false);
        page.setLayout(gridLayout);
        page.setLayoutData(new GridData(GridData.FILL_BOTH));

        Label label = new Label(page, SWT.NONE);
        label.setText("Interface ID:");

        interfaceId = new Text(page, SWT.BORDER);
        interfaceId.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        interfaceId.addKeyListener(new KeyListener() {
            @Override
            public void keyPressed(KeyEvent e) {}

            @Override
            public void keyReleased(KeyEvent e) {
                boolean hasInterfaceID = !interfaceId.getText().trim().isEmpty();
                setMessage(hasInterfaceID ? null : "Please enter an Interface ID", IMessageProvider.ERROR);
                setPageComplete(hasInterfaceID);
            }
        });
    }

    @Override
    public boolean canFlipToNextPage() {
        // 只检查页面是否完成,不要调用getNextPage(避免提前触发进度)
        return isPageComplete();
    }

    public String getInterfaceID() {
        return interfaceId == null || interfaceId.isDisposed() ? null : interfaceId.getText().trim();
    }
}

3. InterfaceDetailsPage修改(移除setVisible中的进度逻辑)

因为进度任务已经在切换前完成,这里只需要在页面显示时获取数据即可:

public class InterfaceDetailsPage extends WizardPage {
    private SelectedServerNode iServer;

    protected InterfaceDetailsPage(SelectedServerNode iServer) {
        super("InterfaceDetailsPage");
        this.iServer = iServer;
        setTitle("Interface ID details");
        setMessage("Provided Interface ID details is shown below");
    }

    @Override
    public void createControl(Composite parent) {
        Composite page = new Composite(parent, SWT.NONE);
        setControl(page);
        page.setLayout(new FillLayout());
    }

    @Override
    public void setVisible(boolean visible) {
        if (visible) {
            InterfacePage interfacePage = (InterfacePage) getWizard().getPage("InterfacePage");
            String interfaceId = interfacePage.getInterfaceID();
            // 这里可以使用进度任务中获取并存储的数据(可在向导类中添加字段存储)
        }
        super.setVisible(visible);
    }
}

关键要点说明

  • setNeedsProgressMonitor(true):必须在向导构造方法中设置,启用进度条支持。
  • getContainer().run(true, true, ...):第一个true表示允许用户取消任务,第二个true表示在UI线程外执行任务,避免阻塞界面。
  • 取消时抛出InterruptedException:当用户点击取消按钮,monitor.isCanceled()返回true,此时抛出中断异常,外层捕获后返回null,向导框架就会停留在当前页面。
  • canFlipToNextPage的实现:只检查页面是否完成,不要调用getNextPage,否则会提前触发进度任务。

内容的提问来源于stack exchange,提问作者Farhan stands with Palestine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:54:09