在SWT的线程开发中,基本思路是:将前台和后台分开为两个类;为后台处理开辟一个线程,让前台和后台处理相互不受影响;前台提供一些组件的操作方法,后台调用方法,并将执行情况写入到前台的组件中显示。
在SWT线程开发中,如果使用一个线程去访问另一个线程,则需要使用到Display对象的asyncExce方法,或者syncExce方法;
在关闭前台窗口时,需要将后台工作停止。由于是多线程,前台窗口关闭后,后台的程序还会在运行,并且回访问到前台的方法,这时,需要调用stop方法,使后台即使停止工作。
下边是一个示例:
前台运行类:
1:前台类中要有一个后台类成员,以便用this进行构造后台类;
2:前台类中要把后台需要访问的界面中的组件设为类的实例变量;
3:在前台类的main中实例化一个前台类对象,并调用open函数进行初始化;
4:前台类的open函数中对窗口进行基本的布局(创建按钮、标签、文本框等)并为组件添加事件监听;
5:可以把后台线程的创建放在事件监听中,也可以放在其外;
1 package cn.com.sino.swt; 2 3 import org.eclipse.swt.SWT; 4 import org.eclipse.swt.events.SelectionAdapter; 5 import org.eclipse.swt.events.SelectionEvent; 6 import org.eclipse.swt.events.VerifyEvent; 7 import org.eclipse.swt.events.VerifyListener; 8 import org.eclipse.swt.layout.GridData; 9 import org.eclipse.swt.layout.GridLayout; 10 import org.eclipse.swt.widgets.Button; 11 import org.eclipse.swt.widgets.Display; 12 import org.eclipse.swt.widgets.Group; 13 import org.eclipse.swt.widgets.Label; 14 import org.eclipse.swt.widgets.ProgressBar; 15 import org.eclipse.swt.widgets.Shell; 16 import org.eclipse.swt.widgets.Text; 17 18 public class GUITest01 { 19 private Display display = Display.getDefault(); 20 private Shell shell = new Shell(); 21 private GUITest task = new GUITest(this); //task为后台处理类 22 //将界面组件设为类的实例变量 23 private Text taskText; //创建任务数文本框 24 private Button openButton; //创建“执行”按钮 25 private Button stopButton; //创建“停止”按钮 26 private ProgressBar progressBar; //创建进度条 27 private Text consoleText; //创建输出调试信息的文本框 28 29 public static void main(String[] args) { //main方法 30 try { 31 GUITest01 window = new GUITest01(); //创建窗口 32 window.open(); //打开窗口 33 } catch (Exception e) { 34 e.printStackTrace(); 35 } 36 } 37 38 public void open(){ 39 shell.setSize(330,330); //设置窗口大小 40 shell.setLayout(new GridLayout()); //设置窗口布局 41 shell.setText("SWT线程示例"); //设置窗口标题 42 Group group = new Group(shell, SWT.NONE); //设置任务数文本框和按钮的组 43 group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 44 group.setLayout(new GridLayout(4,false)); 45 new Label(group, SWT.NONE).setText("任务数:"); //设置任务数文本框 46 taskText = new Text(group, SWT.BORDER); 47 taskText.setText("20"); //默认任务数 48 taskText.setLayoutData(new GridData(100,-1)); 49 taskText.addVerifyListener(new VerifyListener() { 50 public void verifyText(VerifyEvent e) { //只能输入数值 51 e.doit = "0123456789".indexOf(e.text) >=0; 52 } 53 }); 54 openButton = new Button(group, SWT.PUSH); //创建执行按钮 55 openButton.setText("执行"); 56 //对按钮添加事件监听 57 openButton.addSelectionListener(new SelectionAdapter() { 58 public void widgetSelected(SelectionEvent e) { 59 setButtonState(false); //设置两按钮的状态 60 String str = taskText.getText(); //得到任务数 61 final int taskCount = new Integer(str).intValue(); 62 progressBar.setMaximum(taskCount-1); //设置进度条的格数 63 consoleText.insert("后台处理线程开始启动......\n"); 64 65 new Thread(){ //为后台任务创建一个新的线程 66 public void run(){ 67 task.start(taskCount); 68 } 69 }.start(); 70 71 consoleText.insert("后台处理线程启动结束。\n"); 72 } 73 }); 74 75 stopButton = new Button(group, SWT.PUSH); //创建停止按钮 76 stopButton.setText("停止"); 77 stopButton.setEnabled(false); //设置按钮是否可用 78 //对按钮添加事件监听 79 stopButton.addSelectionListener(new SelectionAdapter() { 80 public void widgetSelected(SelectionEvent e){ 81 task.stop(); //后台任务停止 82 } 83 }); 84 85 progressBar = new ProgressBar(shell, SWT.NONE); //创建进度条 86 progressBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 87 //输出调试信息的文本框 88 consoleText = new Text(shell, SWT.MULTI|SWT.BORDER|SWT.V_SCROLL); 89 consoleText.setLayoutData(new GridData(GridData.FILL_BOTH)); 90 //------------------------------------------------------ 91 shell.layout(); 92 shell.open(); 93 while(!shell.isDisposed()){ 94 if(!display.readAndDispatch()){ 95 display.sleep(); 96 } 97 } 98 display.dispose(); 99 } 100 public void setButtonState(boolean bFlag){ 101 openButton.setEnabled(bFlag); 102 stopButton.setEnabled(!bFlag); 103 } 104 //以下为后台类取界面组件的几个get方法 105 public Shell getShell(){ 106 return shell; 107 } 108 public Text getConsoleText(){ 109 return consoleText; 110 } 111 public ProgressBar getProgressBar(){ 112 return progressBar; 113 } 114 }
后台运行类:
1:后台类中要有一个前台界面对象,在构造时获取;
2:在对前台操作的函数中需要调用syncExec,再调用界面类的函数(自定义,可以获取界面组件对象)对界面组件操作;
1 package cn.com.sino.swt; 2 3 import org.eclipse.swt.widgets.Display; 4 5 public class GUITest { 6 private GUITest01 guitest;//前台界面对象 7 private boolean stopFlag;//是否停止的标识 8 9 /** 10 * 取得前台界面兑现 11 * @param taskGUI 12 */ 13 public GUITest(GUITest01 taskGUI){ 14 this.guitest = taskGUI; 15 } 16 /** 17 * 停止执行 18 */ 19 public void stop(){ 20 stopFlag = true; 21 } 22 /** 23 * 开始执行 24 * @param taskCount 25 */ 26 public void start(int taskCount){ 27 stopFlag = false;//将执行状态初始化成执行 28 intsertConsoleText("------后台线程开始执行任务------\n"); 29 for (int i = 0; i < taskCount; i++) { 30 if(stopFlag)//如果发现执行状态为停止,则退出次循环 31 break; 32 try { 33 Thread.sleep(500);//0.5秒一次循环 34 } catch (InterruptedException e) { 35 e.printStackTrace(); 36 } 37 intsertConsoleText("开始处理第"+(i+1)+"个任务...\n");//设置文本内容 38 try { 39 Thread.sleep(500);//休眠0.5秒 40 } catch (InterruptedException e) { 41 e.printStackTrace(); 42 } 43 intsertConsoleText("任务"+(i+1)+"处理完毕\n"); 44 moveProgressBar(i);//设置进度条移动 45 } 46 intsertConsoleText("------后台线程结束执行任务------\n"); 47 setTaskGUIButtonState(true);//刷新界面按钮状态 48 } 49 /** 50 * 界面按钮状态 51 * @param bFlag 52 */ 53 private void setTaskGUIButtonState(final boolean bFlag){ 54 Display.getDefault().asyncExec(new Runnable() { 55 @Override 56 public void run() { 57 guitest.setButtonState(bFlag); 58 } 59 }); 60 } 61 /** 62 * 显示进度条 63 * @param progress 64 */ 65 private void moveProgressBar(final int progress){ 66 Display.getDefault().syncExec(new Runnable() { 67 68 @Override 69 public void run() { 70 guitest.getProgressBar().setSelection(progress); 71 72 } 73 }); 74 } 75 /** 76 * 文本插入 77 * @param str 78 */ 79 private void intsertConsoleText(final String str) { 80 Display.getDefault().syncExec(new Runnable() { 81 82 @Override 83 public void run() { 84 guitest.getConsoleText().insert(str); 85 86 } 87 }); 88 } 89 }
本文转自ZH奶酪博客园博客,原文链接:http://www.cnblogs.com/CheeseZH/archive/2013/03/26/2982841.html,如需转载请自行联系原作者