如何在SWT UI中取消长时间运行的作业



我有一个长时间运行的操作,比如将一个大的zip文件复制到临时目录,提取它,然后将它的内容复制到目标路径。在操作过程中,我还会显示进度条。

我应该在一个独立的SWT UI中实现这一点,它是一个Java项目(非Eclipse/RCP)。

我知道您需要使用一个单独的线程在UI中执行此任务。在我的UI中有一个取消按钮,当单击它时,应该会回滚执行的任务,并优雅地返回到UI/退出,而不会冻结它。我如何才能有效地实现这一点。下面是我开始使用的示例代码。任何帮助都将不胜感激。

import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;

public class TestProgressBar {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        final Display display=new Display();
        final Shell shell=new Shell(display,SWT.MIN|SWT.CLOSE);
        shell.setSize(500,200);
        GridLayout gdLayout=new GridLayout();
        gdLayout.numColumns=2;
        shell.setLayout(gdLayout);

        Composite composite = new Composite(shell, SWT.NONE);
        composite.setLayout(gdLayout);
        GridData gd=new GridData();
        final Label lab=new Label(composite, 0);
        lab.setText("Performing Job :");
        gd.horizontalIndent=10;
        gd.horizontalAlignment=SWT.FILL;
        lab.setLayoutData(gd);
        GridData gdPg=new GridData();
        gdPg.horizontalAlignment=SWT.FILL;
        final ProgressBar bar = new ProgressBar(composite, SWT.NONE);
        bar.setLayoutData(gdPg);
        final int maximum = bar.getMaximum();
        //System.err.println(maximum);
        final Button cancelButton=new Button(composite,SWT.NONE);
        cancelButton.setText("Cancel Copy");

        new Thread() {
            public void run() {
                for (final int[] i = new int[1]; i[0] <= maximum; i[0]++) {
                try {Thread.sleep (10);} catch (Throwable th) {}
                copyOperation();
                    if (display.isDisposed()) return;
                    display.asyncExec(new Runnable() {
                        public void run() {
                        if (bar.isDisposed ()) return;
                            bar.setSelection(i[0]);
                            if(i[0]==maximum) 
                                {
                                    lab.setText("Job Finished!!!");
                                    cancelButton.setEnabled(false);
                                }
                        }

                    });
                }
            }
        }.start();
        shell.open();
        while(!shell.isDisposed())
        {
            if(!display.readAndDispatch())
                    display.sleep();
        }

    }
    protected static void copyOperation() {
        // TODO Auto-generated method stub
        File zipFile=new File("D:\Sample.zip");
        try {
            FileUtils.copyFileToDirectory(zipFile,new File("C:\Users\komail\Desktop"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

为什么不使用布尔cancelled = false,当您单击按钮"取消"时,它会切换为true?复印机定期检查它是假的还是真的。您也可以使用Thread#destroy()

您可以在您的"已取消"变量上创建一个包装器,如下所示:

/**
 * Wrapper on  any type T.
 */
public class Wrapper<T> {
    /**
     * The encapsulated value.
     */
    public T value;
    public Wrapper(T value) {
        this.value = value;
    }
}

并像这样使用:

final Wrapper<Boolean> cancelled = new Wrapper<Boolean>(false);
...
cancelled.value=true;

这样你就有了一个可见的最终字段,你可以更改它的值。

相关内容

  • 没有找到相关文章