第11章 AWT编程
AWT全称是抽象窗口工具集
GUI 图形用户界面
AWT缺点
1.图形显示丑陋
2.AWT组件这能使用这些操作系统共有的组件
3.AWT非常笨拙,是非面向对象的编程模式
总体上Swing组件代替了大部分AWT组件,对AWT有很好的补充和加强
Swing仅提供了能力更强大的用户界面组件,即使是完成采用Swing编写的组件也依然要使用AWT的事件处理机制
java.awt包中提供了两个基类表示图形界面元素
Component 和MenuComponent
代表一个能以图形化方式显示出来 另一个MenuComponent
则代表图形界面的菜单组件
SWT还有两个重要的概念 Container
和LayoutManager
其中Container是一种特殊的Component
它代表了一种容器 而LayoutManager则是容器管理器其他组件的方式
11.1 AWT容器
Container (容器) 是Component
的子类,本身就是一个组件,具有组件的所有性质
AWT主要提供了两种容器类型
1.Window 可独立存在的顶级接口
2.Panel
可作为容器容纳其他组件,但不能独立存在,必须被添加到其他容器中
Frame对象是Window
类的子类,具有如下的特点
1.Frame对象有标题,运行拖拉来改变窗口大小 位置
2.初始化时不可见的
3.默认使用BorderLayout作为其布局管理器
Panel
组件外在表现为一个矩形,该区域可用来盛装其他的组件
Panel容器具有如下几个特点
1. 可作为容器来盛装其他组件
2. 不能单独存在
3. 默认使用FlowLayout作为其布局管理器
ScrollPane是一个带滚动条的容器,它也不能独立存在,必须被添加到其他容器中
ScrollPane容器的特点
1.可作为容器来盛装其他组件,当组件占用空间过大,ScrollPane会自动产生滚动条
2.不能单独存在
3.默认使用BorderLayout作为其布局管理器,通常不允许改变ScrollPane布局管理器
11.3 布局管理器
对于不同的组件,一般都会有不同的最佳大小,一般最佳大小都是平台相关的,为了解决这个问他,java提供了布局管理器
所有的AWT容器都有布局管理器,如果没哟指定布局管理器,则容器使用默认的布局管理器
11.3.1 FlowLayout 布局管理器
panel 和 Applet
都是默认使用FlowLayout布局管理器
组件就像流水一样,想某一个方向上排列,遇到边界就换行。
f.pack() 该方法是Window
容器提供的一个自动调整最佳大小的方法
11.3.2 BorderLayout 布局管理器
Frame Dialog ScrollPane 默认使用BorderLayout布局管理器
BorderLayout布局管理器提供了 东南西北中 五个区域,普通组件可以被放置在任意区域,
使用注意
1.箱BorderLayout添加组件时,需要显示指定添加到那个区域,否则默认添加到中间区域
2.如果想一个区域内增加多个组件会相互覆盖。
11.3.3 GridLayout 布局管理器
GridLayout 局部管理器将容器分割成纵横线分割的网格,每一个网格所占的区域大小相同
GridLayout 布局管理器默认是从左到右从上到下依次添加到每一个网格中,与 Flowout不同的是放置在GridLayout布局管理器中的组件的大小由组件所处的区域来决定的,每个组件将填充满所处空间
11.3.4 GridBagLayout 布局管理器
GridBagLayout 布局管理器功能最强大,但是也最复杂,与GriLayout不同的是,在GridBagLayout布局管理器中,一个组件可以跨越一个或者多个网格,并可以设置各网格的大小互不相同,从而增加布局的灵活性,当窗口改变时,GridBagLayout布局管理器也可以准确的控制窗口大小
为了处理GridBagLayout 中GUI组件的大小、跨越性,java提供了GridBagLayout对象,该对象与特定的GUI组件关联
用于控制GUI组件的大小和跨越性
使用GridBagLayout步骤
1. 创建GridBagLayout布局管理器,并指定容器使用该布局管理器
2. 创建GridBagConstraints对象,并设置该对象的相关属性
3. 调用GridBagLayout对象的方法来创建GridBagLayout对象和收控制组件的关联
4. 添加组件
如果希望一个组件的大小随容器的增大而增大,则必须同时设置控制该组件的GridBagConstraints对象的fill属性和weightx
weigthth 属性
11.3.5 CardLayout 布局管理器
CardLayout布局管理器以时间来管理它里面的组件,它将加入的容器的所有组件看成一叠卡片,每次只有最上面的Component才可以看见
11.3.6 绝对定位
java也提供了那种随意拖动控件的方式,即java也可以被GUI组件进行绝对定位
在java容器中采用绝对定位的步骤如下
1. 将Container的布局管理器设成null
2. 向容器中添加组件时,先调用 setBounds() 或者setSize()
方法来设置组件的大小 位置
但是这种方式是以丧失跨平台作为代价的
11.3.7 BoxLayout 布局管理器(Swing)
它保存了很多GridBagLayout的很多优点,但却没有那么复杂,BoxLayout可以在垂直和水平两个方向上摆放GUI组件
BoxLayout(Container target , int axis) 指定创建基于target容器的BoxLayout布局管理器,该布局管理器里的组件以axis方式排列
BoxLayout 通常和Box容器结合使用,Box是一种特殊的容器,它的特点有点像Panel容器
Box提供了两个静态方法来创建Box对象
createHorizontalBox() 创建一个水平排列的Box容器
createVerticalBox() 创建一个垂直排雷的Box容器
因为BoxLayout 是Swing提供的布局管理器,所有用于Swing组件将会有更好的表现
11.4 AWT常用组件
11.4.1基本组件
CheckboxGroup 用于将多个checkbox组件组合成一组,每组只能有一个被选中
11.4.2 对话框
对话框Dialog 是Window类的子类,是一个容器类,属于特殊的组件 对话框是可以独立存在的顶级窗口
注意
1.对话框通常依赖于其他窗口,就是通常有一个Parent窗口
2.对话框有非模式,和模式两种 当某一个模式的对话框被打开后,该模式对话框总是位于它依赖的窗口之上,在模式对话框被关闭之前,它依赖的窗口无法获得焦点
3.owner 指定该对话框所依赖的窗口,可以是窗口也可以是对话框
4.title 指定该对话框的窗口标题
5.modal 指定该对话框是否是模式的,可以为true
和false
FileDialog 代表文件对话框,用于打开或者保存对话框,
11.5 java 事件处理
11.5.1 java 事件模型的流程
在事件处理的过程中,主要涉及三个类对象
1. Event Source 时间发生的场所,通常就是各个组件,
2. Event 时间封装了GUI组件上发生特定的事情
3. Event Listener 负责监听事件源所发生的事件,并对各种事件作出相应
AWT的事件处理机制是一种委托式事件处理方式
普通的组件(事件源)将事件处理工作委托给特定的对象(事件监听器);当该事件源发生指定的事件时,就通知委托的事件监听器,由事件监听器来处理这个事件
每个
每个组件均可以特对特定的事件指定一个或者多个事件监听器,每个事件监听器也可以监听一个或多个事件源,因为不一个事件源上可能发生多种事件,委托式事件处理方式可以把事件源上可能发生的不同事件分别授权给不同的事件监听器来处理,同一类事件也可以都使用同一个事件监听器
AWT事件处理机制的步骤
1.实现事件监听器类 必须实现 XxxListener接口
2.创建普通组件(事件源) 创建事件监听对象
3.调用addXxxListener()方法将事件监听器对象注册给普通组件
11.5.2 事件和事件监听器
当外部动作在AWT组件上进行操作时,系统会自动生成事件对象,这个事件对象是EventObject子类的实例,该事件会触发注册到事件源上的事件监听器
事件源 new出一个组件
事件 系统自动产生
4.事件监听器 自己实现 核心 必须实现事件监听器接口 addXxxListener()方法将事件监听器对象注册给普通组件
AWT事件类都是 ATWEvent事件类的子类
ATWEvent 是ObjectEvent的子类
1. 低级事件
组件事件 容器事件 窗口事件 焦点事件 键盘事件 鼠标事件 组件绘制事件
2. 高级事件
高级事件时基于基本语义的事件,它可以不和特定动作想关联,而依赖于触发此事件的类
ActionEvent 动作事件 当按钮 菜单项被单机 在TextFile中按Enter
AdjustmentEvent 调节事件 在滑动条上移动滑动条
ItemEvent 选项事件 当用户选中或者取消某项时触发
TextEvent 文本事件 方文本框、文本域里的文字发生改变时触发
11.5.3 事件适配器
原因 :大部分时候程序无需监听出窗口的每一个动作,但是因为要实现WindowListener
接口,所有必须实现接口所有的方法 为此java
提供了事件适配器
原理 : 事件适配器是监听接口的空实现-事件适配器实现了监听器接口,并未该接口的每一个方法都听过了实现,这是一种空实现 (方法体内没有任何代码实现),当需要创建监听器时,可以通过继承事件适配器,而不是监听器接口,重写需要用到的方法
11.5.4 使用内部类实现监听器
事件监听器是一个特殊的java对象,实现事件监听器对象有如下几种形式
1.内部类形式
2.外部类形式
3.类本身作为监听器类
4.匿名内部类
用内部类实现监听器的优点
1. 是内部类可以很好的复用该监听器类
2. 可以自由的访问所有GUI组件
11.5.5 使用外部类实现监听器(比较少见)
少见原因
1.事件监听器通常属于特定的GUI界面,不利于高内聚
2.外部类形式的事件不能自由的访问GUI类中的组件
优点
可以别多个GUI界面共享,而且主要是完成某种业务逻辑的实现
11.5.6类本身作为事件监听器(曾经多 现在少)
使用GUI界面类直接做为事件监听器类,可以直接在GUI界面类中定义事件处理器方法
缺点
1. 可以造成混乱的程序结构GUI界面的职责主要是为了完成界面初始化工作,此时还需要包含事件监听器降低了程序的可读性
2. GUI 界面必须要继承事件适配器,所有继承不了其他的类
11.5.7 匿名内部类实现监听器(实用最广泛)
大部分时候,事件处理器都只使用一次,所以可以定义为匿名内部类更合适
11.6 AWT菜单
11.6.1 AWT 菜单条、菜单和菜单项
AWT中的菜单由如下几个类组合而成
MenuBar :菜单条
Menu : 菜单组件
PopupMenu : 上下文菜单组件(右键菜单组件)
MenuItem : 菜单项组合
CheckboxMenuItem : 复选框菜单项组件
MenuShortcut : 菜单快捷键组件
MenuBar 和Menu都实现了菜单容器接口,所以
MenuBar可用于盛装Menu,而Menu可以用于盛装MenuMenuItem
PopupMenu 上下文菜单无需使用MenuBar盛装
有些时候程序希望对有相似功能的菜单分成一组,此时需要使用菜单分隔符
AWT中添加菜单分隔符有如下两种方法
1. 调用Menu对象addSeparator()方法来添加菜单分隔符
2. 使用添加new MenuItem(“-”)方式来创建菜单分隔符
11.6.2 右键菜单
右键菜单组件使用PopupMenu对象表示,创建右键菜单的步骤如下
1.创建PopupMenu的实例
2.创建多个MenuItem的多个实例,依次加入PopupMenu中
3.将 PopupMenu 加入目标组件中
4.为需要出现的上下文菜单组件编写鼠标监听器
AWT并没有为GUI组件提供实现,而是调用平台的GUI组件来创建和平台一致的对等体,因此程序中TextArea实际上是Window平台上的行为
11.7 在AWT中绘图
11.7.1 画图的实现原理
在Component类里提供了和绘图有关的三个方法
1.paint(Graphics.g)绘制组件的外观
2.update(Graphics.g) 调用paint()方法,刷新组件的外观
3.repaint() 调用update()方法,刷新组件外观
repaint() 调用 update()
调用 paint()
Container 类中的update()方法先以组件的背景填充整个组件区域,然后调用paint()方法重新画组件
程序不应该朱勇调用paint() 和update()方法,这两个方法都是系统负责调用,如果程序希望重新绘制该组件 则应该调用repaint()方法即可,而paint()
和update()通常被重写 通常情况下 程序通过重写paint()方法实现在AWT组件上绘图
11.7.2 使用Graphics
类
Graphics是一个抽象的画笔对象,Graphics可以在组件上绘制丰富多彩的几何图形和位图
11.8 处理位图
Graphics提供了一个drawImage()方法用于创建位图
11.8.1 Image抽象类和BufferedImage实现类
Image类代表位图,但是它是一个抽象类,为此java为它提供了一个BufferedImage子类,这个子类可以访问图形缓冲区的Image实现类
借助BufferedImage 可以在AWT上事件缓冲技术----当需要向GUI组件上绘制图形时,不要直接绘制到该GUI组件上,而是先将图形绘制到BufferedImage
对象中,然后在调用drawImage()方法一次性将BufferedImage
绘制到特定组件上
11.9 剪贴板
剪贴板需要实现
1. 希望保存文字的格式信息
2. 数据的提供者希望实现使用多种格式
3. 不同平台的剪贴板支持传输的对象类型并不完成相同,可以通过jre/lib/flavormap.properties
文件来了解平台支持哪些类型对象
AWT支持两种剪贴板
1.本地剪贴板 如果在同一个虚拟机的不同窗口之间进行数据传递,则使用AWT本地的剪贴板就可以了
2.如果是在不同的虚拟机之间传递数据,那就需要使用系统剪贴板了
11.9.1 系统传递类和接口
AWT中剪贴板相关类都被放到java.awt.datatransfer包下
11.9.2 传递文字
AWT提供了StringSelection用于传输文本字符串,将一段文本内容(字符串对象)放入剪贴板中,步骤如下
1.创建一个Clipborad实例 (可以是本地剪贴板,也可以是系统剪贴板)
2.将需要放入剪贴板的字符串封装成StringSelection对象,
3.调用剪贴板对象的setContents()方法将StringSelection
放入剪贴板中,该方法有两个参数第一个是Transferable对象,代表放入剪贴板的对象,第二个参数是ClipboardOwner对象
11.9.3 使用系统剪贴板传递图像
如果希望将图像放入剪贴板内,则必须提供一个Transferable接口的实现类(它封装了一个image对象,并且外表现为imageFlavor内容)
Transferable接口仅提供了一个StringSelect实现类 用于封装字符串内容 但是JDK在DataFlavor类中提供了一个imageFlavor常量
11.9.4 使用本地剪贴板传递对象引用
DateFlavaor里提供了一个javaJVMLObjectMimeType的常量,该常量是一个MIME类型字符串将java对象放入本地剪贴板中必须使用MIME类型
该MIME类型表示仅将对象引用复制到剪贴板中 对象引用只有在同一个JVM中才有效
本地剪切板是JVM负责维护的内存区,因此本地剪切板会随JVM退出而失效
11.10 拖放功能
在拖放过程中,数据从拖放源直接传递给拖放目标,拖放操作主要涉及两个对象:拖放源和拖放目标
剪贴板和拖放操作也是使用Transferable 接口来封装, 剪切板操作中被传递的数据格式使用DataFlavor来表示拖放操作也一样
程序可以通过继承DropTargetAdapter适配器来创建拖放监听器
11.10.2 拖放源
如何在java程序中创建拖放源 程序需要把拖放内容封装成Transferable对象
1.调用DragSoure的getDefaultDragSource()
方法获得平台相关的DragSource对象
2.调用DragSource对象的createDefaltDragGestureRecognizer(Component c ,int actions , DragGestureListener dgl)
3.为第二步中DragGestureListener 提供实现类