Swing的SwingWorker学习

    一开始使用swing的时候就了解过这个东西.在项目中应用的时候.发现edt操作不能在SwingWorker线程中执行.(这里的edt操作包括什么呢?我以前做的时候只要有new这个关键字.就执行不了..现在就可以了)

一直以为是swing的规范.有很多的限制.最后就没再看这个东西.直到有一天看到这篇文章

 http://vearn.iteye.com/blog/344591

首先赞一下.作者写的非常详细.而且提供了demo.于是我下载了demo,开始读代码.最后终于搞定了这个东东.

于是自己做了个例子.首先是课前准备

 

 
EDT是啥米呀

在Java中,键盘输入、鼠标点击或者应用程序本身产生的请求会被封装成一个事件,放进一个事件队列中,java.awt.EventQueue对象负责从这个队列中取出事件并派发它们。而EventQueue的派发有一个单独的线程管理,这个线程叫做事件派发线程(Event Dispatch Thread),也就是EDT。此外,Swing的绘制请求也是通过EDT来派发的。

 

 

 

 

 

 

 

 

 

 这里就简单提下.关于更详细的介绍请看原文

http://vearn.iteye.com/blog/344591

或者

API:http://202.201.112.11/jpk/apply/teacher/preface/53/api/javax/swing/SwingWorker.html

http://www.javaresearch.org/article/7787.htm

http://www.javaresearch.org/article/7788.htm

 

这里帖下关键代码

 

    private void button_getDataActionPerformed(java.awt.event.ActionEvent evt) {                                         
        //清除表格数据
        table_data.setModel(new javax.swing.table.DefaultTableModel(
                new Object[][]{},
                new String[]{
                    "id", "parent_id", "node_name"
                }));
        //如果要查看EDT阻塞效果
        if (checkbox_edt.isSelected()) {
            //在不采用SwingWorker的时候下面这句你会发现不起作用,因为这是一个EDT事件.
            //只有处理完了这个事件之后.别的改变组件状态的时间才会被执行.这就是EDT阻塞
            label_busy.setVisible(true);//设置载入label显示
            try {
                Thread.sleep(5000);//睡眠5秒
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            setData();
            label_busy.setVisible(false);//设置载入label消失
        } else {//使用SwingWroker
            table_data.setEnabled(false);//设置表格不可用
            button_getData.setEnabled(false);//设置按钮不可用
            label_busy.setVisible(true);//设置载入label显示
            new SwingWorker<DefaultTableModel, Void>() {

                @Override
                protected DefaultTableModel doInBackground() throws Exception {
                    System.out.println("开始执行后台方法...");
                    JLabel jLabel = new JLabel();//测试在非EDT线程中创建组件.我以前做的总是不可以.现在好了.
                    Thread.sleep(5000);//睡眠5秒.因为效果不太明显
                    return getData();//返回取到的数据
                }

                @Override
                protected void done() {
                    System.out.println("后台方法运行结束");
                    table_data.setEnabled(true);
                    button_getData.setEnabled(true);
                    label_busy.setVisible(false);
                    try {
                        //  获取doInBackground方法的返回值
                        table_data.setModel(get());//用get()方法取到上面取得的值
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }.execute();
        }
    }               

 

2009-11-5晚上.


我在回家的路上想起来上次出现edt操作不能在SwingWorker线程中执行这个问题.  是由于用了开源皮肤Substance的问题.回家一试.果真如此..

 

把运行的代码

 

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                TestFrame frame = new TestFrame();
                frame.setVisible(true);
            }
        });
    }
 

改为:

 

    public static void main(String args[]) {
        try {
            JFrame.setDefaultLookAndFeelDecorated(true);
            JDialog.setDefaultLookAndFeelDecorated(true);
            UIManager.setLookAndFeel(new SubstanceBusinessBlueSteelLookAndFeel());
        } catch (Exception e) {
            System.out.println("Substance Raven Graphite failed to initialize");
        }
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                TestFrame frame = new TestFrame();
                frame.setVisible(true);
            }
        });
    }

 

添加substance.jar包..

 

抛出异常:

 

 

org.jvnet.substance.api.UiThreadingViolationException: Component creation must be done on Event Dispatch Thread
        at org.jvnet.substance.utils.SubstanceCoreUtilities.testComponentCreationThreadingViolation(SubstanceCoreUtilities.java:2368)
        at org.jvnet.substance.SubstanceLabelUI.createUI(SubstanceLabelUI.java:68)
        at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:36)
        at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:243)
        at javax.swing.UIDefaults.getUI(UIDefaults.java:751)
        at javax.swing.UIManager.getUI(UIManager.java:1016)
        at javax.swing.JLabel.updateUI(JLabel.java:256)
        at javax.swing.JLabel.<init>(JLabel.java:145)
        at javax.swing.JLabel.<init>(JLabel.java:216)
        at test.TestFrame$2.doInBackground(TestFrame.java:186)
        at test.TestFrame$2.doInBackground(TestFrame.java:181)
        at javax.swing.SwingWorker$1.call(SwingWorker.java:278)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at javax.swing.SwingWorker.run(SwingWorker.java:317)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:619)
 

 

不知道是什么原因....为什么java默认的皮肤可以..开源的就不可以呢...

 

上面的代码是一个按钮点击事件中执行的代码.

详细的例子请见附件

数据库用的是derby.

效果图:

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值