xxian02 2010-10-13 19:05
浏览 524
已采纳

swt 界面假死 使用asyncExec(runnable),没出现多线程的效果

我现在做网络抓取数据包后再还原成html的一个实验,使用swt实现界面,点击开始按钮开始抓包,点击停止按钮停止抓包,想法是抓取到一个数据包就在表格显示,也就是动态刷新界面,当抓取的数据包上千上万的时候界面就假死了,要停止抓包根本停止不了,有时候只有点击鼠标界面就出现无法响应的情况。整个界面代码如下,现在做一个小实验,点击开始按钮,表格创建1000行,第一列为名称,第二列为进度条。但是我想在1000行生成之前停止,但是1000行没生成完之前stop根本不好使,在1000行生成完之后点stop才能停止进度条。哪位大侠,帮忙修改一下吧

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.ProgressBar;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

public class MutiTaskGUI {

    private Shell shell = null;

    private Table table = null;

    public MutiTaskGUI( ){

        //构造方法中调用初始化窗口的方法

        init();

    }

    //初始化窗口方法

    public void init() {

        shell = new Shell();
        shell.setSize(282, 240);    
        shell.setLayout(new GridLayout());

        shell.setText("多线程");

        Button bt = new Button ( shell , SWT.NONE);

        bt.setText("开始一个任务");
        //停止线程
        Button stop = new Button(shell, SWT.NONE);
        stop.setText("stop");
        table = new Table(shell, SWT.BORDER);

        table.setLayoutData( new GridData(SWT.FILL,SWT.FILL,true,true));

        table.setHeaderVisible(true);

        table.setLinesVisible(true);
     

        String[] header = new String[]{"任务","进度","操作"};

        // 创建表头

        for (int i = 0; i < 3; i++) {

            TableColumn col = new TableColumn(table, SWT.NONE);

            col.setText( header[i] );

        }

        //设置表头宽度

        table.getColumn(0).setWidth(80);

        table.getColumn(1).setWidth(150);

        table.getColumn(2).setWidth(80);

        shell.pack();

        //注册创建任务按钮事件

        bt.addSelectionListener( new SelectionAdapter(){

            //当单击创建一个任务按钮时

            public void widgetSelected(SelectionEvent e) {

                //首先创建一个Task对象
                for(int i = 0 ; i < 1000; i++){
                    Task task = new Task();
                //然后在表格中添加一行                    
                task.createTableItem(table);
                //最后启动该任务,该任务为一个线程
                task.start();
                }
            }
        });
        stop.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                // TODO Auto-generated method stub
                Task.setDone(true);
            }

        });
            
    

    }

    //获得和设置属性的getter和setter方法

    public Shell getShell() {

        return shell;

    }

    public void setShell(Shell shell) {

        this.shell = shell;

    }

    public Table getTable() {

        return table;

    }

    public void setTable(Table table) {

        this.table = table;

    }
    public static void main(String[] args) {

        Display display = Display.getDefault();

        MutiTaskGUI mutiTask= new MutiTaskGUI();

        mutiTask.getShell().open();

        while (!mutiTask.getShell().isDisposed()) {

            if (!display.readAndDispatch()) {

                display.sleep();

            }

        }


    }
}

class Task extends Thread {

    //该类的一些属性

    private Table table = null;

    //是否停止的标志

    public static boolean done = false;

    //声明进度条对象

    private ProgressBar bar = null;

    private int min = 0;

    private int max = 100;
    int i = 0;

    //创建表格中的一行

    public void createTableItem(Table table) {
        done = false;
        TableItem item = new TableItem(table, SWT.NONE);
      item.setText(this.getName());
      //  item.setText(new String[]{k +"",i+2+""});

        // 创建一个进度条

        bar = new ProgressBar(table, SWT.NONE);

        bar.setMinimum(min);

        bar.setMaximum(max);

        // 创建一个可编辑的表格对象

       TableEditor editor = new TableEditor(table);

        editor.grabHorizontal = true;

        editor.grabVertical = true;

        // 将进度条绑定到第二列中
       editor.setEditor(bar, item, 1);

    }

    //线程方法体,与前面单个的进度条的程序类似

    public void run() {

        for (int i = min; i < max; i++) {

            if (isDone()) {

                break;

            }
            try {

                Thread.sleep(100);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }
            Display.getDefault().asyncExec(new Runnable(){
          //  table.getDisplay().asyncExec(new Runnable() {
                
                public void run() {

                    if (bar.isDisposed())

                        return;

                    bar.setSelection(bar.getSelection() + 1);

                }

            });

            //如果停止,则结束该线程


        }

    }

    public boolean isDone() {

        return done;

    }

    public static void setDone(boolean done) {

        Task.done = done;

    }

}



  • 写回答

1条回答 默认 最新

  • iteye_7333 2010-10-14 17:02
    关注

    1,对于长时间的任务,不应该在图像线程中完成,如这里的增加1000项表项。应该另起一个线程,然后让图形线程来调度。

    [code="java"]public class MutiTaskGUI {
    private Shell shell = null;

    private Table table = null;

    private addItem t;

    public MutiTaskGUI( ){   
        init();   
    }   
    
    //初始化窗口方法   
    public void init() {
        shell = new Shell();   
        shell.setSize(282, 240);       
        shell.setLayout(new GridLayout());
        Button bt = new Button ( shell , SWT.NONE);   
        bt.setText("开始一个任务");   
        //停止线程   
        Button stop = new Button(shell, SWT.NONE);   
        stop.setText("stop");   
        table = new Table(shell, SWT.BORDER);   
        table.setLayoutData( new GridData(SWT.FILL,SWT.FILL,true,true));   
        table.setHeaderVisible(true);   
        table.setLinesVisible(true);   
        String[] header = new String[]{"任务","进度","操作"};   
        // 创建表头   
        for (int i = 0; i < 3; i++) {
            TableColumn col = new TableColumn(table, SWT.NONE);   
            col.setText( header[i] );
        }
    
        //设置表头宽度   
        table.getColumn(0).setWidth(80);
        table.getColumn(1).setWidth(150);
        table.getColumn(2).setWidth(80);  
    

    // shell.pack();

        //注册创建任务按钮事件   
        bt.addSelectionListener( new SelectionAdapter(){   
            //当单击创建一个任务按钮时   
            public void widgetSelected(SelectionEvent e) {
                t = new addItem(table);
                t.start();
    
                /*
                //首先创建一个Task对象   
                for(int i = 0 ; i < 1000; i++) {
                    Task task = new Task();
                    //然后在表格中添加一行                       
                    task.createTableItem(table);   
                    //最后启动该任务,该任务为一个线程   
                    task.start();
                }*/
            }
        });   
        stop.addSelectionListener(new SelectionAdapter() {   
            public void widgetSelected(SelectionEvent arg0) {   
                t.setDone(true);  
            }
        });   
    }   
    
    public Shell getShell() {return shell;}   
    
    public static void main(String[] args) {
        Display display = Display.getDefault();   
        MutiTaskGUI mutiTask= new MutiTaskGUI();   
        mutiTask.getShell().open();
    
        while (!mutiTask.getShell().isDisposed()) {   
            if (!display.readAndDispatch()) {   
                display.sleep();   
            }
        }
    }   
    

    }

    class addItem extends Thread {
    private Table table;
    public boolean done = false;
    public addItem(Table table) {
    this.table = table;
    }

    public void run() {
        //首先创建一个Task对象   
        for(int i = 0 ; i < 1000; i++) {
            //然后在表格中添加一行 
            try {Thread.sleep(100); } catch (InterruptedException e) {e.printStackTrace();}   
            if(isDone()) break;
            Display.getDefault().asyncExec(new Runnable() {
                public void run() {
                    Task task = new Task();
                    task.createTableItem(table);   
                    task.start();
                }
            });
            //最后启动该任务,该任务为一个线程   
        }
    }
    public boolean isDone() {return done;}
    public void setDone(boolean done) { 
        this.done = done;   
    }
    

    }

    class Task extends Thread {
    //是否停止的标志

    public static boolean done = false;

    //声明进度条对象   
    private ProgressBar bar = null;   
    private int min = 0;   
    private int max = 100;   
    int i = 0;   
    
    //创建表格中的一行   
    public void createTableItem(Table table) {
    

    // done = false;

    TableItem item = new TableItem(table, SWT.NONE);

    item.setText(this.getName());

    // 创建一个进度条

    bar = new ProgressBar(table, SWT.NONE);

    bar.setMinimum(min);

    bar.setMaximum(max);

    // 创建一个可编辑的表格对象

    TableEditor editor = new TableEditor(table);

    editor.grabHorizontal = true;

    editor.grabVertical = true;

    // 将进度条绑定到第二列中

    editor.setEditor(bar, item, 1);
    }

    //线程方法体,与前面单个的进度条的程序类似   
    public void run() {
        for (int i = min; i < max; i++) {
            if (isDone()) {break;}   
            try {Thread.sleep(100); } catch (InterruptedException e) {e.printStackTrace();}   
            Display.getDefault().asyncExec(new Runnable(){   
                //  table.getDisplay().asyncExec(new Runnable() {   
                public void run() {   
                    if (bar.isDisposed())
                        return;   
                    bar.setSelection(bar.getSelection() + 1);   
                }
            });   
            //如果停止,则结束该线程   
        }   
    }   
    
    public boolean isDone() {
        return done;
    }
    
    public static void setDone(boolean done) { 
        Task.done = done;   
    }
    

    }
    [/code]

    改了一下你的例子,你看看,改了一些你的格式,不要介意啊。
    希望 对你有帮助。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记