`
wxq594808632
  • 浏览: 262453 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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.

效果图:

 

 

 

 

  • 描述: 效果图
  • 大小: 7.8 KB
分享到:
评论
7 楼 wxq594808632 2009-12-04  
HeDYn 写道
看下org.jvnet.substance.utils.SubstanceCoreUtilities类下的testComponentCreationThreadingViolation()和testComponentStateChangeThreadingViolation()方法就明白了,它做了一个判断,将这两个方法的内容注释掉就不会有异常信息了。


谢谢解答..回头看看
6 楼 HeDYn 2009-12-04  
看下org.jvnet.substance.utils.SubstanceCoreUtilities类下的testComponentCreationThreadingViolation()和testComponentStateChangeThreadingViolation()方法就明白了,它做了一个判断,将这两个方法的内容注释掉就不会有异常信息了。
5 楼 wxq594808632 2009-11-19  
wave-labs 写道
这种问题的根本原因是:Java Swing不是线程安全的,原因有二个,一个是效率因素,另一个是线程安全的UI工具包通常容易创建出倾向于死锁的程序。

通常在Swing中使用线程有两个简单原则:
1、非常耗时的动作要在一个单独的线程中执行,而不要在事件分派线程(EDT)中执行。
2、在任何线程中都不要碰Swing组件,除了时间分派线程。

要在耗时的线程中操作Swing组件,需要借助EventQueue中的两个静态方法向事件分派线程发送一个事件,从而通知事件分派线程执行对于Swing组件的操作。

上述的原则,对于Java Swing多线程应用是非常非常重要的。


谢谢解答.我现在的疑问是为什么java默认的皮肤可以,开源的那个不可以呢?难道java默认的皮肤绘制组件的时候不碰swing组件?开源的就碰?
4 楼 wave-labs 2009-11-18  
这种问题的根本原因是:Java Swing不是线程安全的,原因有二个,一个是效率因素,另一个是线程安全的UI工具包通常容易创建出倾向于死锁的程序。

通常在Swing中使用线程有两个简单原则:
1、非常耗时的动作要在一个单独的线程中执行,而不要在事件分派线程(EDT)中执行。
2、在任何线程中都不要碰Swing组件,除了时间分派线程。

要在耗时的线程中操作Swing组件,需要借助EventQueue中的两个静态方法向事件分派线程发送一个事件,从而通知事件分派线程执行对于Swing组件的操作。

上述的原则,对于Java Swing多线程应用是非常非常重要的。
3 楼 wxq594808632 2009-11-06  
<p>今天又出现问题.我数据加载和创建组件分开了</p>
<p>我采用swingWorker的方式加载数据.然后创建组件..但是我现在取数据的时间长.创建组件的时间更长..所以还是避免不了EDT堵塞.我该怎么办呢?因为我取到的数据是很多条.我要根据这些数据动态创建大量的组件.所以还是很费时间,创建组件的时候要给组件设置图片..还是慢</p>
<p>不知道有什么解决方案没</p>
<p> </p>
<p>
</p>
<pre name="code" class="java">        new SwingWorker&lt;List&lt;List&lt;Solution&gt;&gt;, Void&gt;() {

            @Override
            protected List&lt;List&lt;Solution&gt;&gt; doInBackground() throws Exception {
                System.out.println("开始执行后台方法...");
                label_busy.setVisible(true);//这里设置一个带加载图片的label显示
                getChoices(setting);//获取数据
                List&lt;List&lt;Solution&gt;&gt; l = getSolutions(choices);
        //在执行完上面的加载数据后.又开始了EDT阻塞!..加载label的加载图片不动了...
                logger.info("数据获取完毕..EDT开始阻塞!");
                return l;
            }

            @Override
            protected void done() {
                System.out.println("后台方法运行结束");
                logger.info("开始卡屏!");
                button_change.setEnabled(true);
                label_busy.setVisible(false);//设置
                try {
                    creatCom(get());//这个方法的执行时间居然比获取数据的时间都长.
//这里的创建组件包括的操作有:首先得到一组选择题的主体.然后查看主题是否包含图片.有相应的属性.有就创建图片.放到一个label中.循环创建.
//创建选择题主体后.循环取他的四个或者多个选项.如果选项有图片..设置之..
                } catch (Exception ex) {

                logger.info("卡屏完毕!");
            }
        }.execute();</pre>
 
2 楼 wxq594808632 2009-11-06  
kjj 写道
不光是swing,凡是牵扯到gui的,例如c#也存在这个问题!!


您说的是edt操作不能在非EDT事件中执行的问题吗?那为什么java默认的皮肤可以呢?开源的那个不可以..
1 楼 kjj 2009-11-05  
不光是swing,凡是牵扯到gui的,例如c#也存在这个问题!!

相关推荐

    java swing 学习教程

    - 为了防止UI线程阻塞,Swing引入了SwingWorker,用于在后台线程执行耗时任务,然后将结果传递回主线程更新界面。 8. **对话框(Dialogs)** - JOptionPane 提供了标准的对话框,如消息框、确认框、输入框等,...

    swing学 习 资 料

    这份"Swing学习资料"的压缩包显然是为了帮助开发者深入理解和掌握Swing的使用。 "精通Java Swing程序设计.chm"是一个Windows平台下的帮助文件,通常包含了详细的教程、示例代码和参考指南。通过这个文件,你可以...

    javaswing学习教程

    Java Swing 是Java GUI(图形用户界面)开发的重要库,它属于Java ...通过以上知识点的学习,你将能够熟练地运用Java Swing 创建各种桌面应用程序,并理解其核心机制。不断实践和探索,你将在GUI编程领域游刃有余。

    学习Swing的文档资料

    通过这个文件,你可以系统地学习Swing的各种知识。 在Swing中,基础组件如按钮(JButton)、文本框(JTextField)、标签(JLabel)等都是JComponent的子类。这些组件可以通过布局管理器(如FlowLayout、...

    使用SwingWorker异步加载JTree

    文件列表中的`asynch_load_tree`可能包含了完整的示例代码,供读者学习和参考。通过深入理解并实践这些内容,开发者能够更好地掌握Java Swing中的异步编程技术,提高应用程序的性能和用户体验。

    java swing漂亮界面 超酷 javaswing教程

    Java Swing 是Java平台上用于构建图形用户界面(GUI)的一个库,它是Java Foundation Classes (JFC)的一部分。...通过不断实践和学习,你可以在Java Swing的世界里创造出超酷的界面设计,为用户提供优质的用户体验。

    Swing是把刀学习代码

    这个“Swing是把刀学习代码”项目显然旨在帮助开发者了解如何利用Swing来创建功能丰富的、具有吸引力的桌面应用。 Swing提供了大量的组件,如按钮、文本框、菜单等,这些组件可以被用来构建用户界面。它的优势在于...

    Swing学习之两个java截屏程序的实现

    这可以通过实现Runnable接口并使用Swing的`SwingUtilities.invokeLater()`或`SwingWorker`类来实现。 5. **说明文档**: 说明.txt文件可能包含了关于如何运行这两个程序的说明,以及可能存在的依赖和注意事项。...

    java-swing精通电子书(chm)

    在实际开发中,Swing提供了SwingWorker类来处理耗时的任务,确保这些任务在后台线程中执行,避免阻塞用户界面。你可能还会学习到如何使用 Nimbus 或 Metal 等LookAndFeel来自定义应用的视觉样式。 最后,Swing示例...

    java swing小程序

    下面将详细讨论Java Swing的主要组件、特性以及如何通过这些小程序进行学习。 Java Swing 提供了一系列丰富的组件,如按钮(JButton)、文本框(JTextField)、标签(JLabel)、面板(JPanel)、滚动窗格...

    java精通swing程序设计.chm

    总之,《Java精通Swing程序设计》是Java开发者深入学习Swing和构建桌面应用的宝贵资源。通过阅读和实践书中的例子,开发者能够掌握Swing的各个方面,提升自己在GUI编程方面的技能,从而能够设计出高效、专业且具有...

    深入学习jfc swing组件

    本资料"深入学习jfc swing组件"旨在帮助开发者全面理解并熟练运用Swing组件。 Swing组件是基于Java AWT(Abstract Window Toolkit)的,但与AWT相比,Swing提供了更多的特性和更好的可定制性。Swing组件通常被称为...

    精通 JAVASWING中文版

    对于 JAVASWING中文版,你可以期待深入理解组件的使用、外观和感觉的定制(NimbusLookAndFeel 或 MetalLookAndFeel)、模态和非模态对话框的应用,以及如何利用 SwingWorker 类实现GUI的异步更新,避免阻塞用户界面...

    java swing游戏开发

    本资料集是专为Java游戏开发爱好者准备的经典资源,包含了几款已经开发完成的游戏实例,同时提供了源码和可执行文件,使得学习者可以通过实践来深入理解Swing在游戏开发中的应用。 首先,Java Swing 提供了多种组件...

    Swing使用范例.rar

    这个压缩包的代码示例可能会涵盖以上提到的一些或全部知识点,通过实际编写和运行这些代码,学习者可以深入理解Swing的工作原理,并逐渐掌握创建Java桌面应用的技能。在实践中不断探索和尝试,将有助于加深对Swing的...

    swing练习1.zip

    在这个名为"swing练习1.zip"的压缩包中,我们可以推测其内容可能包含了一些关于Swing GUI编程的练习题目或示例代码,以帮助学习者巩固Java期末复习的知识。 Swing组件包括按钮、文本框、标签、滚动面板、菜单等,...

    swing sample

    本“Swing示例”压缩包文件提供了学习Swing编程的实例,帮助开发者深入理解其功能和用法。 在Swing中,组件是构建用户界面的基本元素,如按钮、文本框、菜单等。这些组件都继承自java.awt.Component类,但在Swing中...

    Java Swing 2nd Edition

    《Java Swing 2nd Edition》是由Manning出版社于2005年出版的一本权威性的技术书籍,专注于Java Swing框架的深入学习与实践。Swing是Java AWT(Abstract Window Toolkit)库的一部分,用于构建图形用户界面(GUI)。...

    Java 基于Swing的FTP上传下载程序

    因此,通常会在后台线程执行文件传输,通过Swing的`SwingWorker`或者Java 8的`CompletableFuture`来处理。 压缩包中的`djrftp`可能是程序的源代码文件,包含FTP客户端的实现细节。为了更好地理解程序的工作原理,...

    java swing 2nd源码

    7. **Chapter22和Chapter23**:通常会讲解Swing的高级特性和技巧,如自定义组件、SwingWorker(用于后台任务处理)、国际化和本地化支持,或者是Swing的外观和感觉(LookAndFeel)定制。 8. **AppendixA**:通常...

Global site tag (gtag.js) - Google Analytics