Swing之EDT简析

2024-09-03 10:48
文章标签 简析 swing edt

本文主要是介绍Swing之EDT简析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Java Swing 是一个单线程图形库,里面绝大多数的代码不是线程安全的(thread-safe),Swing组件大多数没有做同步线程安全处理,也就是说任何地方都能随便调用,在不同的线程里面随便使用这些API去更新界面元素和设置值,都可能会出现一些问题。
Swing框架使用了Event Queue和EDT(Event-Dispatch-Thread)来保证线程是安全的。在GUI界面上发出的请求事件如窗口移动,刷新,按钮点击等不管是单个的还是并发的,都会背包放入事件队列(Event Queue )里面进行排队,然后事件分发线程(EDT)将会将它们一个个的取出,分派到相应的事件处理方法中。
Swing是单线程图形包就是因为处理GUI事件的事件分发线程只有一个,只要不停之GUI程序,EDT就会永不间断去处理请求。其优点是:1、将同步操作转化为异步操作;2、将并行处理转换为串行处理。
Swing编程时应该注意以下三点:
1.从其他线程访问UI组件及其事件处理器可能会导致界面更新和绘制错误。
2.在EDT上执行耗时任务会使程序失去响应,这会使GUI事件阻塞在队列中得不到处理
3.应该使用独立的线程任务来执行耗时计算或输入输出密集型任务,比如同数据库通信、访问网站资源、读写大数据量的文件

许多程序使用下面方法启动界面,但这是错误的启动UI界面的方法:

public class MainFrame
extends javax.swing.JFrame {public static void main(String[] args)
{new MainFrame().setVisible(true);}
}

尽管这种错误出现在开始,但仍然违反了不应在EDT外的其他线程同Swing组件交互的原则。这个错误尤其容易犯,线程同步问题虽然不是马上显示出来,但是还要注意避免这样书写。

正确启动UI界面应该如下:

public class MainFrame extends javax.swing.JFrame
{public static void main(String[] args)
{SwingUtilities.invokeLater(new Runnable()
{public void run()
{new
MainFrame().setVisible(true);}});}
}

当运行一个Swing程序时,会自动创建三个线程。
1.主线程,负责执行main 方法
2. toolkit 线程,负责捕捉系统事件,比如键盘、鼠标移动等,程序员不会有任何代码在这个线程上执行。Toolkit线程的作用是把自己捕获的事件传递给第三个线程,也就是事件派发线程。
3. 事件派发线程(EDT,Event Dispatcher Thread),顾名思义是用来派发事件(根据事件找到对应的事件处理代码)的线程。EDT接收来自 toolkit 线程的事件,并且将这些事件组织成一个队列,EDT的工作内容就是将这个队列中的事件按照顺序派发给相应的事件监听器,并且调用事件监听器中的回调函数,这也意味着,所有的事件处理代码都是在EDT而不是主线程中执行。
4. 上面说到EDT中维护了一个事件的队列,并且它们是按照顺序派发的。由于事件派发是单线程的操作,所以只有等待前面事件监听器的回调函数执行完毕,才能够执行组件更新的操作,以及继续派发后面的事件。这样导致的一个后果就是:当在一个事件监听回调函数中做了耗时的操作,那么,界面会因此停住,并且界面上所有控件失效(不可触发)。
解决这个问题的方法是:在事件处理函数中将耗时的操作放到新线程(一般称之为工作线程)中执行,而不是让其在EDT中执行。
一个窗口,有一个按钮和一个label。点击按钮,系统将做模仿导入数据的动作,导入数据之前需要检测数据的合法性。并且,检测数据和导入数据这两个步骤都需要耗费一定的时间。
如果没有之前说到的EDT的概念,那么你可能会这么做:

importBtn.addActionListener(newActionListener() {@Overridepublicvoid actionPerformed(ActionEvent e) {try{lb.setText("1.检查数据合法性...");Thread.sleep(3000);//模仿检测数据合法性lb.setText("2.正在导入数据...");Thread.sleep(4000);//模仿导入数据lb.setText("3.导入成功!");}catch (InterruptedException e1) {e1.printStackTrace();}}});

但是,如果运行一下的话,会发现现象是这样:点击按钮,界面卡住,按钮变得不可触发,直到一段时间(7秒)之后界面显示“3.导入成功”。期间并没有显示“1.检查数据合法性”和“2.正在导入数据”。
这个现象印证了上面说的理论:当事件派发线程中正在执行的事件监听函数执行完毕,才能进行UI组件的刷新操作,并且派发事件队列中的下一个。

package test;import java.awt.FlowLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;public class SwingThreadTest3 extends JFrame {/*** */private static final long serialVersionUID = -6785759504284102780L;private JProgressBar progressBar = new JProgressBar();      //进度条private JTextField text = new JTextField(10);private JButton start = new JButton("Start");private JButton end = new JButton("End");private boolean flag = false;private int count =0;private GoThread t = null;      //继续线程private Runnable run = null;    //更新组件线程public SwingThreadTest3() {this.setLayout(new FlowLayout());add(progressBar);text.setEditable(flag);add(text);add(start);add(end);start.addActionListener(new Start());end.addActionListener(new End());   run = new Runnable() {public void run() {progressBar.setValue(count);text.setText("Completed : " + String.valueOf(count) + "%");             }           };}class GoThread extends Thread {@Overridepublic void run() {while (count < 100) {try {Thread.sleep(100);  //线程沉睡} catch (Exception e) {e.printStackTrace();} if (flag) {count++;SwingUtilities.invokeLater(run);    //将对象排到事件派发线程的队列中}}}}private class Start implements ActionListener {public void actionPerformed(ActionEvent e) {flag = true;if(t == null) {t = new GoThread();t.start();}}}private class End implements ActionListener {public void actionPerformed(ActionEvent e) {flag = false;}}public static void main(String[] args) {SwingUtilities.invokeLater(new Runnable() {public void run() {SwingThreadTest3 s3 = new SwingThreadTest3();s3.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);s3.setSize(300, 300);s3.setVisible(true);}});}}

参考资料:http://983836259.blog.51cto.com/7311475/1724198
http://developer.51cto.com/art/201201/313034.htm

这篇关于Swing之EDT简析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1132753

相关文章

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

ElasticSearch底层原理简析

1.ElasticSearch简述 ElastiaSearch(以下简称ES)是一个基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全文搜索引擎,支持RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。ES设计用于云计算中,能够进行实时搜索,支持PB级搜索,具有稳定,可靠,快速,安装使用方便等

JavaSwing项目ATM自动提款机(mysql数据库)+详细报告

目  录 第一章 引言... 1 1.1 设计目的... 1 1.2 相关开发工具介绍... 1 第二章 数据库需求分析... 2 2.1 系统功能分析... 2 2.2 功能模块设计... 2 第三章 数据库概念结构设计... 3 3.1 概念模型... 3 3.2 E-R图... 3 第四章 数据库逻辑结构设计... 4 4.1 关系模型设计... 4 4.2 数据模型的优化... 4 第五

面向对象程序设计之链表 list 的简析(C++)

简介:链表是一个双向的结构,与string与vector不同的是他不支持[]访问,因为链表是由一个节点一个节点连接而成的,并不连续。我们可以在常数量级内对于链表进行插入与删除数据 1.构造函数 我们在cplusplus.com中可以查到链表总共有四种构造的方式:1.无参构造(默认构造);2.使用n个val构造;3.迭代器区间构造;4.拷贝构造 接下来让我们简单创建一个链表

7、java swing 添加 jcheckbox复选框

总体上而言,Java Swing编程有两大特点:麻烦、效果差。        麻烦是说由于设计器的使用不方便(如果您希望使用窗体设计器通过快速拖拽控件建立您的Java Swing GUI程序,请您使用MyEclipse 8.5以上版本,并且需要最高使用权限),所有代码都得手写,如果没有好的编码规范和注释习惯。自己都会被代码淹没。效果差是指运行时的界面。具体的您可以自己尝试发现。 通过一段代码来

5、Java Swing布局管理器(FlowLayout、BorderLayout、CardLayout、BoxLayout、GirdBagLayout 和 GirdLayout)

5、Java-Swing常用布局管理器       应用布局管理器都属于相对布局,各组件位置可随界面大小而相应改变,不变的只是其相对位置,布局管理器比较难以控制,一般只在界面大小需要改是才用,但即使这样,为了操作方便,也只是在大的模块下用布局管理器,在一些小的模块下还是用绝对布局。在一些没要求界面大小改变的窗口,一般采用绝对布局比较容易,但对于后期的修改来说比较麻烦。 5.1、

4、Swing在JPanel中添加背景图片方法

4、Jpanel面板中加载背景图片 在实际应用Java做界面的过程中,常常会涉及到加载背景图片以使页面美化。下面整理了一个小模块以便于调用。 1 package com.tntxia.commonswing.panel; 2 3 import java.awt.*; 4 import javax.swing.JPanel; 5 6 /** 7 * 有背

Java Swing中几种常见对话框(文件对话框、消息对话框、输入对话框、确认对话框、颜色对话框)

1、Dialog类主要方法        JDialog类和JFrame都是Windows的子类,二者的实例都是底层容器,但二者有相似之处也有不同的地方,主要区别是JDialog类创建的对话框必须要依靠于某个窗口。        创建对话框与创建窗口类似,通过建立JDialog的子类来建立一个对话框类,然后这个类的一个实例就是一个对话框。对话框是一个容器,它的默认布局是BorderLayout

Java+Swing实现学生选课管理系统

Java+Swing实现学生选课管理系统 一、系统介绍二、系统展示1.课程查询2.课程添加3.退课 三、系统实现四、其他1.其它系统2.获取源码 一、系统介绍 本系统实现了学生登录和管理员登录,学生实现选课,查看已选课程,修改密码,查看学生信息功能。管理员实现选课信息的增删改查,学生信息查询,学生密码修改功能。 二、系统展示 1.课程查询 2.课程添加 3.退课

【原创】java+swing+mysql学生考勤管理系统设计与实现

个人主页:程序员杨工 个人简介:从事软件开发多年,前后端均有涉猎,具有丰富的开发经验 博客内容:全栈开发,分享Java、Python、Php、小程序、前后端、数据库经验和实战 文末有本人名片,希望和大家一起共同努力,一起进步,顶峰相见。 开发背景: 随着信息技术的飞速发展,各行各业都在积极利用信息平台来提高管理效率。在教育领域,信息技术的引入不仅改变了传统的教学模式,也极大地提升了学校的