当前课程知识点:Java程序设计 > 第七章 图形用户界面 > 7.7-事件派发机制 > 事件派发机制
大家好
欢迎回来继续学习
Java语言程序设计
这一节我们来了解一下
事件派发机制
相信大家可能已经有
这样的疑问了
为什么我写了事件响应代码
然后我对这些事件源上面
注册了事件监听器
这个时候我去操作
这些事件源的时候
这个事件就会被传到
事件监听器那儿
然后就能够触发一段
响应代码的执行
那么这个机制到底是怎么实现的呢
好 这一节我们就来了解一下
Java里面的事件派发机制
在Swing中这些组件
都不是线程安全的
然后我们这门课没有涉及到
多线程的问题
那我可以简单解释一下
也就是说我们这些Swing组件呢
不能够说有多个程序段
并发对它进行操作
比如说一个文本栏里面的文字
你正在修改
修改完了还没提交呢
那么如果另一个程序段
并行执行的时候
也去修改这个文字
那不就乱了嘛
对吧
包括一些radiobutton, checkbox的选项也是
你不同的并发程序段
怎么能同时去选择它呢
那不就最后选择的结果
互相干扰就乱了嘛
所以从这个角度来讲
大家应该比较容易理解
就是说一个组件
被某一个程序段在操作的时候
那么其他的程序段
是不能并行的也去操作它的
那么这样情况下呢
怎么能够保证它的操作
都是(串形)执行的
一个程序段对组件的操作
完全完成了以后
另外的程序段才可以去操作它
怎么保证这一点呢
在Java中呢专门有一个线程
叫做事件派发线程
我们所有的这些事件
都要由事件派发线程去派发
接下来我们就来了解一下
这个事件派发的机制
事件派发线程呢
是用来执行组件的
事件处理程序的线程
也就是说我们写了
那些事件处理程序以后
那么执行的时候
都要由事件派发线程来派发
那么线程的概念呢
大家可能还是陌生的
我们这门课并不涉及到
多线程的部分
我们可以理解
简单的理解线程
也就是说你在同一个程序中
可能有多段代码
他们的执行从逻辑上
是可以并行执行的
如果并行执行的话呢
这样对CPU的利用效率
就会比较高
那么每一个执行的程序段
它就是一个线程
可以简单粗浅的这样去理解
在GUI程序中呢
它都有一个事件派发线程
那么这个事件派发线程呢
会依次从系统的事件队列中
去取出相应的事件并且处理
那它遵循的原则是
一定要执行完上一个
事件的处理程序以后
才会去处理下一个事件
那么我们事件监听器里面的
那些方法呢
都是在事件派发线程中
去启动执行的
比如说ActionListener里面的
actionPerformed的方法
它就是一个事件监听器里面的方法
它就是要由事件派发线程去执行
我们设计好了这样一个
GUI界面以后
由谁来启动这个GUI界面呢
谁把它显示出来呢
虽然我们可以在主方法中
去启动和显示GUI
但是更好的办法
是把它交给事件派发线程来启动
实际上我们可以调用
invokeLater或者invokeAndWait
这两个方法之一
请事件分发线程
运行我们希望运行的代码
我们只要将这段代码
放在一个实现了Runnable接口的
对象的run方法中就可以了
那么这个run方法
要作为参数传给invokeLater
那么这样的话呢
事件派发线程就会去启动
这一段代码去执行
关于Runnable的意思是什么
什么是Runnable接口
这个大家如果想深入了解的话
可以去参考一些Java教程的
多线程的这个部分的内容
我们这门课不太涉及到这些内容
我们只是说能看到例题中这样用
大家能模仿着用就可以了
这里这个invokeLater是异步的
它不等其中的代码执行完就返回了
返回到调用者了
而invokeAndWait呢是同步的
它要等到代码执行完才返回
那么这个时候呢
大家如果说要用invokeAndWait
就要很小心
要避免这个死锁
关于死锁呢
也要在java教材中的多线程
这一部分会有介绍
大家感兴趣的话可以去参考
由于这个invokeLater
有这样的一种功能
所以我们就可以把启动
GUI界面的代码呢
放在一个Runnable对象的
run方法中
传给invokeLater作为参数
那这样的话事件派发线程
就会启动GUI了
现在我们来回忆一下
前面介绍布局管理的时候
曾经介绍过有一种布局
叫CardLayout
那么接下来我们就来看看
我们怎么样编写程序代码
来实现这种布局
现在我们来看这个
我们怎么样实现这个CardLayout
这样一种布局的效果
首先我们要去实现这个
ItemListener
就是我们这个例题
就是说当你在这儿点
拉下这个下拉菜单的时候
那么你这里面呢
会看到两个选项
一个是JButtons
一个是JTextField
你选不同选项的时候呢
相应的卡片就会显示在前面
就像你一摞卡
一摞扑克牌或者说卡片
你选择把哪一个放到前面
显示一样
这样可以比较节省地方
所以我们当拉下这个下拉菜单
选这个选项的时候
就会导致一个
一个选项变化的事件发生
所以这个时候
我们就需要一个ItemListener
来监听这个事件
这个简单例子中
我们就让当前这个类
自己来实现这个ItemListener
这样的话我们就注册
当前对象自己作为
事件监听器对象就可以了
好
那接下来我们准备好两个字符串
这个是表示这个BUTTONPANEL
这个JPanel With JButtons
这个字符串
还有一个是表示这个
TextField这个Panel
就是JPanel with JTextfield
这两个字符串先准备好
后面要用的
好 接下来我们来看
这是一个addComponentToPanc
这个方法是把一些组件
加到面板上去
首先我们要构造一个中间容器
JPanel
这个JPanel会默认使用
这个FlowLayout这种布局
然后这个大家看这个string数组
comboBoxItems
这个string数组里有两个string
把它初始化成什么呢
就是刚才准备好的两个字符串
将来会在这个下拉列表中
表示是两个选项
好 那现在来构造这个JComboBox
就是我们拉下来可以有选项
这个列表
用这个comboBoxItems这个数组
作为参数
那么就是给它规定了
有两个选项了
构造了这样一个JComboBox cb
好 那要给它设置成可编辑吗
false 是不可编辑的
你只能使用它
然后呢要给它添加事件监听器
刚才说了
本类就实现了一个事件监听器接口
ItemListener
所以就添加当前对象自己
作为事件监听器就可以了
然后接着
接下来我们来看
要把它这个ComboBox加到哪儿去呢
加在我们刚才构造的这个Panel
中间容器上
ComboBoxPanel
把这个原子组件
添加到一个中间容器上去
接下来又构造一个JPanel
是干什么用的呢
是放底下的内容的
放底下内容的
有一个要放这个一组Button
另外一个就要放这个文本栏
所以我们看到这是窗口
是有几部分组成的
上面这是一个
中间容器是一个Panel
上面放了一个JComboBox
下面不同的卡片
也有一个自己的中间容器JPanel
分别放了一组Button
和这个TextField
我们来看这是放了一组Button
这个是放了这个TextField
放在card1 card2这两个
中间容器的JPanel里面去了
然后我们要在构造
再又构造一个JPanel干什么呢
我们是要将这两个card
card1 card2
都在放到另外一个中间容器上去
所以他们背后还有一个中间容器
所以我们又构造一个JPanel
那么这个JPanel呢
它的布局是什么
就是我们要实现的这个
CardLayOut
是CardLayOut
然后往上放了两张card
现在我们可以看到呢
上面这个JComboBox
放在一个Panel上面准备好了
底下分别准备好了两个card
那好我们再来看这个方法头
这个方法它是要将组件
添加到一个Panel上面去
所以它的参数
有一个container是一个容器
那么现在我们把这些都准备好了以后
把它们要所有的这些
我们准备好的东西
要添加到参数传过来的
这个容器上面去
所以我们来看参数传过来这个Pane
也是一个Panel容器
要添加什么呢
把这个ComBoxPane这个Panel
还有这个放了两个不同的card的
这个cards
这个JPanel都添加上去
都添加上去
然后用的是这个BorderLayout
分别用BorderLayout
把它放到不同的区域了
好 接下来看这个方法呢
是ItemStateChange
这就是要响应事件的这个方法
事件响应方法
在这个方法中就要切换这个卡片
根据这个事件对象的内容
按照要求去切换卡片
我们来看这个切换卡片的方法
是先取得它的Layout对象
Card.Layout GetLayout对象
那么得到了这个对象以后
我们知道它的应该是CardLayout
所以把它转换成CardLayout类型
这就是CardLayout引用
然后去调用show方法
去调用show方法
显示这个cards
这一摞卡片中的某一张
哪一张呢
cards上面装了一摞卡片了
一摞这个卡
然后显示哪个呢
我们要看这个Event对象
这个事件对象里面
去取出你选择的这个Item
就是你点一下
就生成了一个ItemEvent
对吧
那么这个事件对象里面
就记录了你的选项到底是哪个
根据你这个选项
把它换成
转换成字符串
然后就去显示这张card
这就是响应事件
进行了这个显示card的一种切换
再看下面这个方法
createAndShowGUI
创建并且显示这个GUI的界面
那你要想显示GUI
首先你要有一个主窗口
所以构造一个JFrame
字符串是它的标题
然后要设置它的窗口关闭
按纽的含义
接下来我们要去构造一个
CardLayoutDemo对象
然后调用这个
addComponentToPane
把这个组件加到
它的顶层的Panel上面
加到哪儿去呢我们来看
是加到这个Frame的顶层容器上面
顶层这个它用getContentPane
取得它顶层容器
把其他的组件添加上去
添加上去以后呢
然后去安排一下(pack)
就是正好让它大小适合容纳
这些组件
然后让它setVisible可显示
这些是做不同功能的几个方法
都准备好了
那接下来我们看主函数中
看了点什么
去启动这个程序的主窗口
去显示这个GUI界面呢
这就是调用了这个
SwingUtilities这个包里面的
invokeLater方法
那么在这个里面呢
我们注意new了一个Runnable
Runnable它是一个接口
是一个在多线程中程序中
用得着的接口
那么new了一个Runnable
但是怎么能new Runnable呢
其实不是这个意思
new一个实现了Runnable接口的
匿名内部类的对象
关键是我们需要将想做的动作
想执行的代码
要放在这个覆盖的run方法里面
想干什么呢
createAndShowGUI
就是创建和显示GUI就是这个方法
就是这个方法
所以是这样的
不是直接去执行它
而是去调用invokeLater
用一个实现了Runnable接口的对象
作为参数
而这个实现Runnable的
这个匿名内部类里面
它的run方法里面
就包含着我们想执行的操作
就是启动这个GUI
那么像这样做了以后呢
那个事件派发线程
就会负责来启动这个GUI界面了
在这一节呢
我们简单的了解了一下
这个事件派发的机制
我们自己写程序的时候呢
并不需要跟这个事件派发线程
去打很多交道
只是我们需要了解这种机制以后
我们就知道如何去让事件派发线程
来启动GUI
我们可以使用这个invokeLater方法
知道这一点就可以了
另外就是我们可以放心的
只去写事件响应代码
注册事件监听器
然后就等着事件派发线程
帮我们去派发事件就可以了
好 这一节内容就是这些
-1.0-导学
--1.0-导学
-1.1-Java与面向对象程序设计简介
--第一章 Java语言基础知识--1.1-Java与面向对象程序设计简介
-1.2-基本数据类型与表达式
-第一章 Java语言基础知识--1.2-基本数据类型与表达式
-1.3-数组
--1.3.1-数组
-第一章 Java语言基础知识--1.3-数组
-1.4-算法的流程控制
--第一章 Java语言基础知识--1.4-算法的流程控制
-1.5-第一章小结
-第一章编程练习题
-课件
--外部链接
-Java环境配置、Eclipse使用、Helloworld程序详解
--使用eclipse建立Java项目、编写和运行Java程序
-Java数据类型
--Java整数类型
--Java浮点类型
--数据类型实战
--数据类型转换
--Java强制类型转换精度损失示例与表达式中的数据类型转换
-Java数组
-Java变量
--Java的变量
-命令行参数
--命令行参数的介绍
-2.0-导学
--2.0-导学
-2.1-面向对象方法的特性
--第二章 类与对象--2.1-面向对象方法的特性
-2.2-1-类声明与对象创建
--第二章 类与对象--2.2-1-类声明与对象创建
-2.2-2-数据成员
--第二章 类与对象--2.2-2-数据成员
-2.2-3-方法成员
--第二章 类与对象--2.2-3-方法成员
-2.2-4-包
--2.2-4-包
--第二章 类与对象--2.2-4-包
-2.2-5-类的访问权限控制
--第二章 类与对象--2.2-5-类的访问权限控制
-2.3-1-对象初始化
--第二章 类与对象--2.3-1-对象初始化
-2.3-2-内存回收
--第二章 类与对象--2.3-2-内存回收
-2.4-枚举类
--2.4-枚举类
--第二章 类与对象--2.4-枚举类
-2.5-应用举例
--2.5-应用举例
-2.6-第2章小结
-第二章编程练习题
-课件
--第二章课件
-3.0-导学
--3.0-导学
-3.1.1-3.1.2-类继承的概念和语法
--第三章 类的重用--3.1.1-3.1.2-类继承的概念和语法
-3.1.3-隐藏和覆盖
--第三章 类的重用--3.1.3-隐藏和覆盖
-3.2-Object 类
--第三章 类的重用--3.2-Object 类
-3.3-终结类与终结方法
--第三章 类的重用--3.3-终结类与终结方法
-3.4-抽象类
--3.4-抽象类
--第三章 类的重用--3.4-抽象类
-3.5-泛型
--3.5-泛型
--第三章 类的重用--3.5-泛型
-3.6-类的组合
--3.6-类的组合
-3.7-小结
--3.7-小结
-第三章编程练习题
-课件
--课件
-4.0-导学
--导学
-4.1-接口
--接口
--第四章 接口与多态--4.1-接口
-4.2.1-4.2.2-类型转换
--类型转换
--第四章 接口与多态--4.2.1-4.2.2-类型转换
-4.2.3-方法的查找
--方法的查找
--第四章 接口与多态--4.2.3-方法的查找
-4.3-多态的概念
--多态的概念
--第四章 接口与多态--4.3-多态的概念
-4.4-多态的应用举例
--多态的应用举例
--第四章 接口与多态--4.4-多态的应用举例
-4.5-构造方法与多态性
--构造方法和多态性
--第四章 接口与多态--4.5-构造方法与多态性
-4.6-本章小结
--本章小结
-第四章编程作业
-课件
--课件
-5.0-导学
--5.0-导学
-5.1.1-5.1.2-异常处理的概念
--第五章 输入输出--5.1.1-5.1.2-异常处理的概念
-5.1.3-5.1.5-异常的处理
--第五章 输入输出--5.1.3-5.1.5-异常的处理
-5.2-输入输出流的概念
--输入输出流的概念
--第五章 输入输出--5.2-输入输出流的概念
-5.3.1-写文本文件
--写文本文件
--第五章 输入输出--5.3.1-写文本文件
-5.3.2-读文本文件
--读文本文件
--第五章 输入输出--5.3.2-读文本文件
-5.3.3-写二进制文件
--写二进制文件
--第五章 输入输出--5.3.3-写二进制文件
-5.3.4-读二进制文件
--读二进制文件
-5.3.5-File类
--File类
-5.3.6-处理压缩文件
--处理压缩文件
-5.3.7-对象序列化
--对象序列化
-5.3.8-随机文件读写
--随机文件读写
-5.4-本章小结
--本章小结
-课件
--课件
-6.0-导学
--导学
-6.1-Java集合框架介绍
--第六章 对象群体的组织--6.1-Java集合框架介绍
-6.2-主要接口及常用的实现类
--第六章 对象群体的组织--6.2-主要接口及常用的实现类
-6.3-常用算法
--常用算法
-6.4-数组实用方法
-6.5-基于动态数组的类型(Vector, ArrayList)
--基于动态数组的类型(Vector, ArrayList)
-6.6-遍历Collection
-6.7-Map接口及其实现
-6.8-第6章小结
--第6章小结
-课件
--课件
-7.0-导学
--导学
-7.1-绘图
--绘图
-7.2-Swing基础
--Swing基础
-7.3-Swing的层次
--Swing的层次
-7.4-布局管理
--布局管理
-7.5-内部类
--内部类
-7.6-事件处理的基本概念
-7.7-事件派发机制
--事件派发机制
-7.8-顶层容器
--7.8-顶层容器
-7.9-中间层容器(一)
-7.10-中间层容器(二)
-7.11-原子组件(一)
-7.12-原子组件(二)
-7.13-原子组件(三)
-7.14-其它Swing特性
-7.15-第7章小结
-课件
--课件