从一个简单的例子看UI多线程处理(基于eclipse的SWT组件)

/*
 * 创建日期 2005-4-7
 *
 * TODO 要更改此生成的文件的模板,请转至
 * 窗口 - 首选项 - Java - 代码样式 - 代码模板
 */
package csvviewer;

import java.io.BufferedReader;
import java.io.*;
import java.io.IOException;

import javax.swing.table.TableColumn;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
 * @author Administrator
 *
 *
 */
public class CSVViewer {
    /**
     * @author yantong
     *
     *
     */

    private Shell shell;

    private Display display;

    private Text textBox;

    private Table table;

    private Label statusBar;

    private MenuItem mItemOpen;

    private final String[] EXTENSIONS = { "*.csv", "*" };

    private String fileName;

    public Shell open(Display display) {
        this.display = display;

        shell = new Shell(display);
        shell.setText("CSVViewer");
        shell.setLayout(new GridLayout(1, true));

        Composite comp = new Composite(shell, SWT.NO_FOCUS);
        comp.setLayout(new GridLayout(1, true));
        GridData compGrid = new GridData();
        compGrid.horizontalAlignment = GridData.FILL;
        compGrid.verticalAlignment = GridData.FILL;
        compGrid.grabExcessHorizontalSpace = true;
        compGrid.grabExcessVerticalSpace = true;
        comp.setLayoutData(compGrid);

        textBox = new Text(comp, SWT.SINGLE | SWT.BORDER);
        textBox.setText("");
        GridData textGrid = new GridData();
        textGrid.horizontalAlignment = GridData.FILL;
        textGrid.grabExcessHorizontalSpace = true;
        textBox.setLayoutData(textGrid);

        createTable(comp);

        statusBar = new Label(shell, SWT.LEFT);
        GridData gridData = new GridData();
        gridData.horizontalAlignment = GridData.FILL;
        statusBar.setLayoutData(gridData);
        statusBar.setText("指定CSV文件");

        Menu menubar = new Menu(shell, SWT.BAR);
        shell.setMenuBar(menubar);
        MenuItem mItemFile = new MenuItem(menubar, SWT.CASCADE);
        mItemFile.setText("文件(&F)");
        Menu menuFile = new Menu(mItemFile);
        mItemFile.setMenu(menuFile);
        mItemOpen = new MenuItem(menuFile, SWT.PUSH);
        mItemOpen.setText("打开(&O)");
        mItemOpen.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                getOpenFileName();
                if (fileName != null) {
                    new Thread(new CSVLoader()).start();
                    //                    loadBegin();
                    //                    loadFile();
                    //                    loadEnd();
                }
            }
        });
        //new MenuItem(menuFIle,SWT.SEPARATOR);
        MenuItem mItemExit = new MenuItem(menuFile, SWT.PUSH);
        mItemExit.setText("关闭(&X)");
        mItemExit.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                close();
            }
        });

        shell.open();
        return shell;
    }

    /**
     * @param parent
     */
    private void createTable(Composite parent) {
        table = new Table(parent, SWT.FULL_SELECTION | SWT.BORDER);
        GridData tableGrid = new GridData();
        tableGrid.horizontalAlignment = GridData.FILL;
        tableGrid.verticalAlignment = GridData.FILL;
        tableGrid.grabExcessHorizontalSpace = true;
        tableGrid.grabExcessVerticalSpace = true;
        table.setLayoutData(tableGrid);
        table.setLinesVisible(true);
        table.setHeaderVisible(true);
        TableColumn col = new TableColumn(SWT.LEFT);
        col.setWidth(100);
        table.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                setTableSelectedIndex();
            }
        });
    }

    private void getOpenFileName() {
        FileDialog openDialog = new FileDialog(shell, SWT.OPEN);
        openDialog.setFilterExtensions(EXTENSIONS);
        fileName = openDialog.open();
    }

    private void close() {
        shell.close();
        shell.dispose();
    }

    private void setTableSelectedIndex() {
        int index = table.getSelectionIndex();
        statusBar.setText("第" + (index + 1) + "行");
    }

    //以下为了用其它线程处理显示过程
    /* 1.生成Runnable类,可以做成一个单独文件,为了方便只在CSVViewer中制作一个内部类 */
    /* 2.修改菜单处理程序,将调用loadBegin,loadFile,loadEnd的地方修改,
     * 替换为线程执行,new Thread(new CSVLoader()).start();
    /* 3.将loadBegin,loadFile,loadEnd方法都放在线程CSVLoader中处理,
     * 使其能在其它线程中执行, */
    /* 4.线程化问题,org.eclipse.swt.SWTException:
     * 问题在于操作SWT的widget处理在UI线程之外的某处被运行
     * 可使用display的syncExec和asyncExec方法将处理移送到UI线程中*/
    /* 5.向UI移送处理,追加asyncExec方法(CSVLoader追加utility方法checkAsyncExec())
     * 修改loadBegin,loadFile方法,改为使用checkAsyncExec方法在UI流中运行*/
    class CSVLoader implements Runnable {

        private long beginTime;
       
        public void run() {
            loadBegin();
            loadFile();
            loadEnd();
        }

        private void loadBegin() {
            checkAsyncExec(new Runnable(){
                public void run(){
                    mItemOpen.setEnabled(false);
                    textBox.setText(fileName);
                    Composite comp = table.getParent();
                    table.dispose();
                    createTable(comp);
                    comp.layout();
                   
                    statusBar.setText("读入中...");
                }
            });
            beginTime = System.currentTimeMillis();
//            mItemOpen.setEnabled(false);
//            textBox.setText(fileName);
//            Composite comp = table.getParent();
//            table.dispose();
//            createTable(comp);
//            comp.layout();
//            statusBar.setText("读入中...");
//            beginTime = System.currentTimeMillis();
        }

        private void loadFile() {
            BufferedReader reader = null;
            try {
                File file = new File(fileName);
                if (!file.exists()) {
                    return;
                }

                reader = new BufferedReader(new FileReader(file));

                String line = null;
                while ((line = reader.readLine()) != null) {
                    final String[] datas = line.split(",");
                    //为了在run方法内参照loadFile方法的local变量datas,将其定义为final
                    boolean isOK = checkAsyncExec(new Runnable(){
                        public void run(){
                            if (table.isDisposed()){
                                return;
                            }
                           
                            for (int i = table.getColumnCount(); i < datas.length; i++) {
                                TableColumn column = new TableColumn(SWT.LEFT);
                                column.setWidth(100);
                            }
                           
                            TableItem item = new TableItem(table, SWT.NULL);
                            item.setText(datas);
                        }
                    });
                   
                    if (!isOK){
                        return;
                    }              
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        }

        private void loadEnd() {
            checkAsyncExec(new Runnable(){
                public void run(){
                    if (mItemOpen.isDisposed()||statusBar.isDisposed()){
                        return;
                    }
                   
                    mItemOpen.setEnabled(true);
                    long end = System.currentTimeMillis();
                    statusBar.setText("读入完了:处理时间"+(end-beginTime)+"微秒");
                }
            });
//            mItemOpen.setEnabled(true);
//            long end = System.currentTimeMillis();
//            statusBar.setText("读入结束:处理时间" + (end - beginTime) + "微秒");
        }
       
        private boolean checkAsyncExec(Runnable r) {
            if (!display.isDisposed()) {
                display.asyncExec(r);
                return true;
            } else {
                return false;
            }
        }

    } 

    public static void main(String[] args) {
        Display display = new Display();
        CSVViewer viewer = new CSVViewer();
        Shell shell = viewer.open(display);
        while (!shell.isDisposed()) {
            //通过readAndDispatch()方法显示画面和时间处理
            //在SWT中,把生成显示项目并在循环内执行方法的线程称为UI线程。
            //如果该UI线程调用处理花费的时间过长的话,那应用程序看上去就像停止了一样。
            //应该在单独的线程中执行由用户时间触发的长时间操作,以便事件循环线程快速返回,
            //并从应用程序的队列中访存下一个事件。
            //(必须用显式锁定和序列化来控制从其他线程访问小窗口和平台API)
            if (!display.readAndDispatch())
                display.sleep();
            //如果队列中没有事件可用,则显示进入睡眠状态,以使其它应用程序有机会运行。
        }

        display.dispose();
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值