- 浏览: 842313 次
- 性别:
- 来自: 草帽海贼团
文章分类
最新评论
-
大维啊:
估计只有你自己能明白
Java安全沙箱机制 -
moonljt521:
第五种方式,如果构造里想传入参数怎么做,例如android的 ...
单例模式的七种写法 -
javaDADY:
怎么感觉在讨论茴香豆的茴字有几种写法?
单例模式的七种写法 -
Wallen_Han:
Mr.Cheney 写道这样的:Mr.Cheney 写道还有一 ...
单例模式的七种写法 -
Wallen_Han:
60love5 写道第三种稍微有点Java基础就知道是错的,被 ...
单例模式的七种写法
本人最近想写一个仿QQ,初学Swing对线程机制不太了解,所以在网上搜集了一些资料,结合自己的一些代码和想法,现将Swing线程机制以及invokeLater和invokeAndWait的学习所得分享给大家。
Swing线程机制
首先swing是单线程的,这个是这篇文章的前提,也是意义所在,当swing界面程序启动的时候,会启动3个进程,
1、主线程
2、系统工具包线程:负责捕获操作系统事件,然后将事件转换成swing的事件,然后发送到事件派发线程EDT
3、事件派发线程(EDT):将事件派发到各个组件,并负责调用绘制方法更新界面
所有的事件,例如键盘,鼠标事件,都会由工具包线程转换成swing事件,然后放到事件队列EventQueue中,而这个EventQueue的派发机制是由EDT来管理的。
所以任何修改组件状态的方法都应该在EDT中执行,包括构造方法。Swing这样的构造原理经常会造成的情况就是,在EDT中执行长时间的事件,使EDT不能及时响应更新界面的事件,就是所说的界面卡住,这种不光是新手就是比较熟练的程序员也会犯的一个错误。所以必须避免在EDT中执行长时间的操作,而避免的方法就是多线程,启动另外的线程来处理冗长的操作,比如操作数据库,读写文件等,在这过程中可能要更新界面来给用户以提示,比如显示一个进度条,过一段事件更新一下界面,但是在EDT以外的线程中更新界面都是无效的,这在前面已经说过,要更新界面就要将对界面的更新操作放到EDT中,但是事件又是在另外的线程中执行的,要解决这个问题就要使用SwingUtilities提供的一个方法了 invokeLater,
public void actionPerformed(ActionEvent e){ new Thread(new Runnable(){ //do something SwingUtilities.invokeLater(new Runnable(){ public void run(){ //update the GUI } }); }).start; }
这个方法的作用就是将一个更新界面的任务放到EDT中,EDT会在适当的时候进行调用以更新界面。invokeLater负责创建一个含有Runnable的特定事件,并让其在EDT中排队等待调用,当被调用时就会运行Runnable中的run方法进行派发。
invokeLater和invokeAndWait的区别
与invoikeLater一样,invokeAndWait也把可运行对象排入事件派发线程的队列中,invokeLater在把可运行的对象放入队列后就返回,而invokeAndWait一直等待知道已启动了可运行的run方法才返回。如果一个操作在另外一个操作执行之前必须从一个组件获得信息,则invokeAndWait方法是很有用的。
一般我们用到invokeLater,都是为了执行事件派发线程中的代码,将一段更新UI事件的代码派发到EventQueue中,但是我们可以从事件派发线程中调用invokeLater,却不能从事件派发线程中调用invokeAndWait,下面我们用代码来例证它们的不同:
SwingConsole.java文件:
package swing.utilities; import javax.swing.*; public class SwingConsole { public static void run(final JFrame f, final int width, final int height) { SwingUtilities.invokeLater(new Runnable() { public void run() { f.setTitle(f.getClass().getSimpleName()); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(width, height); f.setVisible(true); } }); } }
TestAction.java文件:
import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import swing.utilities.SwingConsole; public class TestAction extends JFrame { private static final long serialVersionUID = -7462155330900531124L; private JButton jb1 = new JButton("确定"); private JTextField txt = new JTextField(10); public TestAction() { jb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String name = ((JButton) e.getSource()).getText(); txt.setText(name); } }); setLayout(null); add(txt); add(jb1); txt.setBounds(50, 100, 200, 30); jb1.setBounds(270, 100, 70, 30); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { SwingConsole.run(new TestAction(), 500, 500); } }); } }
我们在启动main线程的时候就把整个SwingConsole派发到EventQueue中,而本身SwingConsole已经处在EventQueue中,我们调用invokeLater 没问题,运行正常!
再看我们修改之后的:
SwingConsole.java文件:
package swing.utilities; import java.lang.reflect.InvocationTargetException; import javax.swing.*; public class SwingConsole { public static void run(final JFrame f, final int width, final int height) { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { f.setTitle(f.getClass().getSimpleName()); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(width, height); f.setVisible(true); } }); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } }
TestAction.java文件:
与前面一样
运行结果,出现异常:Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
在这里,我们把SwingConsole中的invokeLater改成了invokeAndWait,而之前SwingConsole已经处在EventQueue中了。
所以我们可以总结出它们的不同:可以从事件派发线程中调用invokeLater,却不能从事件派发线程中调用invokeAndWait,从事件派发线程调用invokeAndWait的问题是:invokeAndWait锁定调用它的线程,直到可运行对象从事件派发线程中派发出去并且该可运行的对象的run方法激活,如果从事件派发线程调用invoikeAndWait,则会发生死锁的状况,因为invokeAndWait正在等待事件派发,但是,由于是从事件派发线程中调用invokeAndWait,所以直到invokeAndWait返回后事件才能派发。
在这里我们还可以看到,在main函数里,我们在一开始就把整个操作都置于EventQueue中,这样虽然安全,但是不适合新手,因为新手很容易犯刚才那样的错误,一不小心就用了invokeAndWait而产生死锁。对于swing中的线程,我也还没有找到理想的处理机制,所以暂时就先到此,以后有经验才跟大家分享吧。
=======================================================================
2011年1月5日14:39:28更新
1.比较保险的方式是,一旦swing组件被实现(setVisiable(true)/show()/pack()或者父组件已经被实现),所有改变组件状态的代码或者依赖于组件状态的程序代码,全部需要给EDT执行。
2.JComponent的repaint、revalidate和invalidate等方法在内部已经将更新UI的事件POST进了EDT线程,所以你可以在其他任何线程任何事件调用这几种方法。
public void revalidate() { if (getParent() == null) { // Note: We don't bother invalidating here as once added // to a valid parent invalidate will be invoked (addImpl // invokes addNotify which will invoke invalidate on the // new Component). Also, if we do add a check to isValid // here it can potentially be called before the constructor // which was causing some people grief. return; } if (SwingUtilities.isEventDispatchThread()) { invalidate(); RepaintManager.currentManager(this).addInvalidComponent(this); } else { Runnable callRevalidate = new Runnable() { public void run() { revalidate(); } }; SwingUtilities.invokeLater(callRevalidate); } }
评论
发表评论
-
解决eclipse每次启动maven很慢
2012-11-14 12:31 17785好久没有用eclipse了,离开人人后maven私有仓库当然也 ... -
Debug控
2011-08-02 14:34 3519我是一个debug控,很 ... -
泛型のwhy&how
2011-07-21 18:35 1373Why,Java为什么需要 ... -
【分享】Findbugs反模式
2011-05-20 09:54 5228FindBugs解释 FindBugs 是一个静态分 ... -
Findbugs反模式
2011-05-20 09:46 0FindBugs介绍 FindBugs 是一个静态分 ... -
正则表达式Mini版
2010-10-27 12:14 13201.句点符号:. 条件 ... -
Eclipse下jar包版本不一致等常见问题
2010-09-15 20:18 7946我借这个平台简单说说Eclipse下配置环境需要注意的几点 ... -
我承认我没有if(xxx != null)
2010-09-08 12:08 2913昨天正在编码兴头时 ... -
jtextfield限制字数与数字输入
2010-02-21 15:40 64import javax.swing.text.*; p ... -
在重写了对象的equals方法后,还需要重写hashCode方法吗?
2009-08-19 21:08 1973首先说建议的情况: 比如你的对象想放到Set集合或者是想作为 ... -
第五惑:初始化和动态绑定之间的小小冲突
2009-04-04 23:46 1195今天骑车去都江堰了,很累很累,没准备好今天该发什么Tips,所 ... -
第四惑:属性是否被动态绑定?
2009-04-03 17:11 1120众所周知,方法可以被动态绑定,在子类被向上转型为父类时,虚拟机 ... -
第三惑:类型被动使用举例
2009-04-02 13:04 1385当类型属于被动使用的 ... -
第二惑:类型在没有被完全初始化之前就生成实例对象所表现的情况
2009-04-01 13:41 1450public class MainTest { publi ... -
第一惑:类初始化时,final修饰的静态字段的表现方式
2009-03-31 16:27 1799计划从今天开始,模仿一下jythoner大哥,不过不是Java ... -
Java动态绑定虚拟机实现
2009-03-25 20:19 1684今天在51CTO看到一篇很好的介绍Java动态绑定的文章。先转 ... -
Java虚拟机简单介绍
2009-03-25 20:17 110请参考:http://cantellow.iteye.com/ ... -
Java夜未眠·经典句子选载
2009-03-25 20:16 2771最近在读前辈蔡学镛《Java夜未眠·程序员的心声》,几天就看完 ... -
代码签名和认证
2009-03-25 20:06 1728要对一段代码作担保或 ... -
Java安全沙箱机制
2009-03-25 20:05 4585说明,本文部分内容转 ...
相关推荐
Swing 线程之SwingUtilities invokeLater docx
序 前言 第一部分 Swing基础 第1章 简介 1.1 Swing的历史 1.2 轻量组件与重量组件的比较 1.3 Swing组件 1.3.1 AWT的替代组件... 2.4.2 SwingUtilties类的invokeLater和invokeAndWait方法 2.5 本章回顾
chm格式的,内容很全面。就是一本书。 目 录 序 前言 第一部分 Swing基础 ... 2.4.2 SwingUtilties类的invokeLater和invokeAndWait方法 2.5 本章回顾 第3章 Swing组件的体系结构 .......
Swing线程之SwingUtilities.invokeLater解释Java开发Java经验技巧共7页.pdf.zip
基于Java Swing界面制作的一个简单的文本编辑器,带软件启动画面,功能... 如果需要从事件处理(event-handling)或绘制代码以外的地方访问UI,那么可以使用SwingUtilities类的invokeLater()或invokeAndWait()方法。
在main方法中,我们使用SwingUtilities.invokeLater方法在事件分派线程中创建了一个MyFrame对象。这是为了确保Swing应用程序在正确的线程中运行,避免出现并发访问问题。 Swing还提供了许多其他的GUI组件和功能,如...
程序通过创建Ball、Paddle和Block类来实现游戏的运行逻辑,其中...程序的入口 main 方法通过调用 SwingUtilities.invokeLater 方法来创建一个线程并运行 BreakBlockGame 类,以避免在主线程中创建和显示 Swing 组件。
NULL 博文链接:https://futeng.iteye.com/blog/1733683
在main()方法中,通过SwingUtilities.invokeLater()方法启动主界面,确保界面在事件分派线程(Event Dispatch Thread)中创建和显示。 注意:此示例只是一个简单的演示,没有包括输入验证和错误处理等完整的功能。...
程序创建一个窗口,包含输入分数的文本框、计分按钮、查询按钮、显示比分的文本区域和退出按钮。用户可以通过输入分数进行计分,通过查询按钮...最后,通过SwingUtilities.invokeLater方法确保在正确的线程中运行程序。
java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new Explorer().setVisible(true); } }); } // Variables declaration - do not modify private javax.swing.JButton jButtonGo; ...
接下来,创建一个线程,用于不断下降方块和刷新游戏画面。在方块下降的过程中,检查是否可以继续下降,如果不行,则将方块固定并消除一行方块,同时更新得分。方块下降过程中,还可以旋转方块。最后,创建一个...
聊天室 这是一个很轻的版本聊天工具,...最后修复Jlist渲染的bug,解决方案是使用swingutility.invokelater方法在更新准备好和需要更新时更新UI,这将保证所有UI渲染都在事件调度线程中。 除了这个修复,其余的都很好。
EventQueue.invokeLater(new Runnable() {//使事件派发线程上的可运行对象排队。当可运行对象排在事件派发队列的队首时,就调用其run方法 public void run() { try { final Test1 frame = new Test1();//捕获...
SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(UIManager. getSystemLookAndFeelClassName()); } catch (Exception exception) { exception....
EventQueue.invokeLater(new Runnable() { public void run() { try { Login frame = new Login (); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } public Login...
内含源码和api 欢迎加群讨论:148079860 运行依赖 JDK 7+ for littleluck NinePatch for littleluck 快速入门 下载littluck,并添加到你的项目中 Startup.java public class Startup { public static void main...
import javax.swing.*; public class Demo extends JFrame { private final class ButtonActionListener implements ActionListener { private final ImagePanel imagePanel; private Thread imageThread; ...
技术背景:本项目使用Java Swing技术,数据库采用SQLServer 2000,本项目的开发和测试都是在Windows平台下进行的,但由于Java的跨平台性,本 系的移植性很强,也适用于其它主流的操作系统。 3. 类图 图3.1类图 3. ...
EventQueue.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(new org.jvnet.substance.skin.SubstanceOfficeBlue2007LookAndFeel()); JFrame....