eclipse学习笔记!(9) ----- SWT Designer 下 SWT的线程(*很不错应用*)

  • 简介 

        多数情况下,GUI界面编程不需要考虑线程问题,SWT已经帮助我们隐藏了底层的线程调用。但一些特殊应用,却不得不涉及SWT线程编程。
        在实际项目开发中,一种常见的应用是:单击前台界面的执行后,在后台要做一些任务处理,任务执行情况要反映在界面上,而且还不能影响前台界面的其他操作
        这种应用的实现思路如下:
前台界面和后台程序分开2个类。
为后台程序另开一个线程,这样就可以让前台操作不受后台影响了。
前台界面提供一些可操作的组件的方法,后台处理程序调用这些方法,将执行情况的字符串写到前台界面组件中。
        这种思路必须解决一个关键问题:界面本身有一个默认线程,后台程序又是另外一个线程。那么该如何在一个线程中访问另外一个线程呢?
        (1) 为后台新开一个线程,这要用到JDK中线程的知识,代码如下:

         new  Thread() // 新开一个线程,这是匿名内部类的写法
            public void run(){
                
//开始后台任务
            }

        }
.start(); // start表示立即开始线程

      (2) 从后台处理线程中访问前台界面组件,关键在于使用display对象,因为display主要负责管理时间循环和控制UI线程和其他线程之间的通信。display的具体使用方法如下:

        Display.getDefault().asyncExec( new  Runnable() {//又是一个匿名内部类写法
            public void run(){
                
//对前台界面的操作
            }

        }
);

      在这里的display对象很关键,因此顺便给出得到display对象的2种方法:
Display.getDefault(),得到一个默认的display对象,应用程序一般只需要一个display对象。
Display.getCurrent(),得到当前运行线程所在的display对象,如果生成2个以上的display对象,则可用此方法。 

  • 一个SWT线程的实例

本实例分2个类:一个前台界面类,一个后台处理类。实例功能说明如下:
      单击“GO”按钮时,开始后台处理。
      单击“STOP”按钮,立即中断后台处理。
      后台处理的任务数根据前台界面文本框的值来决定。
      进度条将实时反映后台处理的进度。
      底部的文本框将以文字形式反映后台处理的进度情况。
      实例具体代码如下:

1. 前台界面类

import  org.eclipse.swt.SWT;
import  org.eclipse.swt.events.SelectionAdapter;
import  org.eclipse.swt.events.SelectionEvent;
import  org.eclipse.swt.events.VerifyEvent;
import  org.eclipse.swt.events.VerifyListener;
import  org.eclipse.swt.layout.GridData;
import  org.eclipse.swt.layout.GridLayout;
import  org.eclipse.swt.widgets.Button;
import  org.eclipse.swt.widgets.Display;
import  org.eclipse.swt.widgets.Group;
import  org.eclipse.swt.widgets.Label;
import  org.eclipse.swt.widgets.ProgressBar;
import  org.eclipse.swt.widgets.Shell;
import  org.eclipse.swt.widgets.Text;

public   class  TaskGUI  {
    
private Display display = Display.getDefault();
    
private Shell shell = new Shell();
    
private Task task = new Task(this);//Task是后台处理类,需要传入一个TaskGUI类型参数
    
//将界面组件设为类的实例变量
    private Text taskCountText;//可输入任务数的文本框
    private Button startButton;//开始
    private Button stopButton;//结束
    private ProgressBar progressBar;//显示的任务条
    private Text consoleText;//显示当前后台进度的信息条
    
//主函数
    public static void main(String[] args){
        
try{
            TaskGUI window 
= new TaskGUI();
            window.open();
        }
catch(Exception e){
            e.printStackTrace();
        }

    }

    
//前台页面的执行方法,显示出可操作的前台界面、
    public void open() {
        shell.setSize(
300,300);
        shell.setLayout(
new GridLayout());
        Group group 
= new Group(shell,SWT.NONE);
        group.setLayoutData(
new GridData(GridData.FILL_HORIZONTAL));
        group.setLayout(
new GridLayout(4,false));
        
        
new Label(group,SWT.NONE).setText("taskCount:");
        taskCountText 
= new Text(group,SWT.BORDER);
        taskCountText.setText(
"10");
        taskCountText.setLayoutData(
new GridData(100,-1));
        taskCountText.addVerifyListener(
new VerifyListener(){
            
public void verifyText(VerifyEvent e) //only input NO.
                e.doit = "0123456789".indexOf(e.text)>=0;                
            }
            
        }
);
        startButton 
= new Button(group,SWT.PUSH);
        startButton.setText(
"GO");
        startButton.addSelectionListener(
new SelectionAdapter() {//点击开始按钮
            public void widgetSelected(SelectionEvent e) {
                setButtonState(
false);//点击后,2个Button发生变化
                
//得到任务数,多线程使用的变量要求类型为final
                String str = taskCountText.getText();
                
final int taskCount = new Integer(str).intValue();
                
//设置进度条的格数
                progressBar.setMaximum(taskCount-1);
                consoleText.insert(
"back Thread run start... ...  ");
                
//为后台新开一个线程,运行,当run方法结束(即后台的start()结束),线程自动销毁
                new Thread(){
                    
public void run(){
                        task.start(taskCount);
                    }

                }
.start();
                consoleText.insert(
"back Thread run end... ...  ");
            }

        }
);
        stopButton 
= new Button(group,SWT.PUSH);
        stopButton.setText(
"STOP");
        stopButton.setEnabled(
false);        
        stopButton.addSelectionListener(
new SelectionAdapter() {
            
public void widgetSelected(SelectionEvent e) {
                task.stop();
//后台执行stop方法,实际是要后台任务停止
            }

        }
);
        progressBar 
= new ProgressBar(shell,SWT.NONE);
        progressBar.setLayoutData(
new GridData(GridData.FILL_HORIZONTAL));
        
//下面2个是设置,文本框的显示格式,第2行的如果不加则会看不到全部信息了
        consoleText = new Text(shell,SWT.MULTI|SWT.BORDER|SWT.V_SCROLL);
        consoleText.setLayoutData(
new GridData(GridData.FILL_BOTH));
        shell.layout();
        shell.open();
        
while(!shell.isDisposed()){
            
if(!display.readAndDispatch()){
                display.sleep();
            }

        }

    }

    
public void setButtonState(boolean bFlag){//设置页面的2个按钮状态
        startButton.setEnabled(bFlag);
        stopButton.setEnabled(
!bFlag);
    }

    
//为后台取得页面组件写的几个GET方法
    public Shell getShell(){
        
return shell;
    }
    
    
public Text getConsoleText(){
        
return consoleText;
    }
    
    
public ProgressBar getProgressBar(){
        
return progressBar;
    }

}

 2. 后台任务类

import  org.eclipse.swt.widgets.Display;
public   class  Task  {
    
private TaskGUI gui;//通过构造器得到前台界面对象
    private boolean stopFlag;//是否停止的标志
    
//构造器 取得前台界面对象
    public Task(TaskGUI taskGUI){
        
this.gui = taskGUI;
    }
    
    
public void stop(){
        stopFlag 
= true;
    }

    
//就是前台run方法的执行内容,这个方法结束,则前台new的那个线程销毁
    public void start(int taskCount){
        stopFlag 
= false;//将执行状态初始化执行
        insertConsoleText("backGO start ... ...  ");
        
for(int i=0;i<taskCount;i++){
            
if(stopFlag){//点击stop按钮则这个属性为true,跳出循环
                break;
            }

            
try{//每隔1秒一次循环
                Thread.sleep(1000);
            }
catch(InterruptedException e){
                e.printStackTrace();
            }

            
//页面上的信息累加
            insertConsoleText("task"+(i+1)+"the end ");
            
//移动进度条的进度
            moveProgressBar(i);
        }

        insertConsoleText(
"the thread end of the task!! ");        
        setTaskGUIButtonState(
true);
    }

    
//修改页面按钮的状态
    private void setTaskGUIButtonState(final boolean bFlag){
        Display.getDefault().asyncExec(
new Runnable(){
           
public void run(){
               gui.setButtonState(bFlag);
           }

        }
);
    }
    
    
private void moveProgressBar(final int progress){
        Display.getDefault().asyncExec(
new Runnable(){
            
public void run(){
                gui.getProgressBar().setSelection(progress);
            }

         }
);
    }
    
    
private void insertConsoleText(final String str){
        Display.getDefault().asyncExec(
new Runnable(){
            
public void run(){
                gui.getConsoleText().insert(str);
            }

         }
);
    }
    
}

 程序说明:
从上面代码的执行结果可以看到,前台new 了一个新的 thread 后,后面的那句文本依然可以输出,可以明确的说明,new了一个线程后,前台,后台线程是互补干扰的独自运行。当start方法结束时,后台的线程就自动销毁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值