2013-08-17 63 views
0

我有一个长时间运行的操作,例如将大型压缩文件复制到临时目录,解压缩并将其内容复制到目标路径。在操作过程中,我还会显示一个进度条。如何在SWT UI中取消长时间运行的作业

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

我知道您需要使用单独的线程才能在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(); 
     } 



    } 


} 

回答

1

为什么不使用一个布尔cancelled = false,当你点击该按钮取消此切换到正确的?复印机会定期检查它是错误还是真实的。 您还可以使用Thread#destroy()

+0

谢谢,但是你不能在一个监听器中使用一个全局变量而不使它最终,并且最终变量不能被分配:( – Abbas

+0

@Abbas你可以修改'Listener'中的'field',即类成员变量。 – Baz

0

您可以在“取消”变量创建一个包装是这样的:

/** 
* 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; 

这种方式,你有一个最终的字段是可见的,你可以改变它的值。

相关问题