第 9 章 Java的图形用户界面
2012-3-7 Java面向对象程序设计教程 2
主要内容
? 9.1 JFC的组成
? 9.1.1 AWT
? 9.1.2 Swing
? 9.1.3 Drag and Drop
? 9.1.4 Java 2D
? 9.1.5 Java Accessibility
? 9.2 应用程序和小程序界面图形化
? 9.2.1 Swing的根面板
? 9.2.2 小程序的典型例子
? 9.2.3 应用程序的典型例子
? 9.2.4 结合小程序和应用程序的典型例子
? 9.3 AWT的组件布局管理模型
? 9.3.1 基于策略模式的授权模型
? 9.3.2 布局管理器类
? 9.4 AWT的事件处理模型
? 9.4.1 基于观察者模式的授权模型
? 9.4.2 事件源
? 9.4.3 事件类
? 9.4.4 事件监听器
? 9.4.5 创建事件监听器对象
9.1 JFC的组成
2012-3-7 Java面向对象程序设计教程 4
Java基础类
? Java Foundation
Classes,JFC
? JFC由 5个 API组成:
AWT,Swing,Java
2D,Drag and Drop
和 Accessibility
2012-3-7 Java面向对象程序设计教程 5
基于对等组件的 AWT
? AWT( Abstract Window Toolkit)是一个独立
平台的窗口工具组件集,它依赖于对等组件
( Peer),而对等组件是一种本地 GUI组件,由
AWT类管理。
? AWT的作用是给用户提供基本的界面组件,如按
钮、列表、菜单等等。
? AWT组件中,包含有对其对等组件的大量实用操
作,而 AWT类仅仅是对等组件外围的包装与操作
工具,因此,对等组件可以快速产生一个 GUI工
具组件。
? 对于最初的 AWT,其开发组只用了不到 6个星期
的时间,但存在大量的缺陷。
2012-3-7 Java面向对象程序设计教程 6
重量组件
? AWT最初只包括与本地对等组件相关联的
组件,称为重量组件( Heavyweight
component)。
? 这些组件在它们自己的本地不透明窗口中
绘制,这样使用将花费昂贵的代价,而且
在更改其默认行为时,不可以为其扩展子
类。
? 它们必须是矩形的,而且不能有透明的背
景。
2012-3-7 Java面向对象程序设计教程 7
轻量组件
? 在 AWT 1.1版本中引入 。
? 轻量组件直接扩展了 java.awt.Component或
java.awt.Container。
? 轻量组件没有本地对等组件,它不在本地不透明窗口中绘
制,而是在它们的重量容器窗口中绘制。
? 轻量组件不会导致与它们关联的不透明窗口的性能损失,
而且还可以有透明的背景。
? 透明的背景使显示的轻量组件可以是非矩形的,虽然所有
组件(重量的或轻量的)都有一个矩形边框。
? 在轻量组件的容器中必须有一个是重量组件,否则无法在
窗口内绘制轻量组件。
2012-3-7 Java面向对象程序设计教程 8
AWT组件的分类
? java.awt.Component
菜单、按钮、标签、列表等组件的抽象基本类,AWT中大约有一半的
类是从它这里扩展出来的。
? java.awt.Container
扩展 Component的抽象基本类。在容器中可以包含多个组件,我们
可以使用容器将相关组件组合成一个整体,以简化程序 GUI的设计,
同时有利于组件的显示安排。由 Container演变出来的类有 Panel、
Applet,Window,Dialog和 Frame等。
? java.awt.LayoutManager和 java.awt.LayoutManager2
定义容器中组件位置和尺寸方法的接口。 Java中定义了几种默认的布
局管理器,如 FlowLayout,BorderLayout,CardLayout、
GridLayout和 GridBagLayout等
? java.awt.Graphics
定义组件内图形操作的基本类,每个组件都有一个相关的图形对象。
2012-3-7 Java面向对象程序设计教程 9
Swing和 AWT的关系
? Swing是用来替代 AWT的重量组件,而不是用来替代 AWT本身。
? Swing使用 AWT最好的部分来建立一个新的轻量组件集,并且丢弃了
AWT中有问题的重量组件部分。
? Swing利用了 AWT的底层组件,包括图形、颜色、字体、工具包和布
局管理器。
? Swing没有使用 AWT的顶层组件,除了 Frame,Window和 Dialog
类,它们分别被 Swing的重量组件 JFrame,JWindow和 JDialog所
扩展。
2012-3-7 Java面向对象程序设计教程 10
插入式界面样式
? Swing支持插入式界面样式( Pluggable Look-
and-Feel),它的基础是模型-视图-控制
( Model-View-Controller,MVC)架构。
? Swing组件的代理是 ComponentUI类的一个扩
展,它是 Swing工具包中的一个 Java类,其中定
义了所有 UI代理的公共行为,这些行为可以在扩
展组件中进行修改。
? 对于插入式界面样式,Swing组件的 UI代理负责
显示组件和处理输入事件的视图-控制器。
? 当 Swing组件配备了一个修改过的组件 UI时,组
件的可视外观或事件处理都是可以修改的。
2012-3-7 Java面向对象程序设计教程 11
插入式界面样式举例:
StyleChooser.java
2012-3-7 Java面向对象程序设计教程 12
Swing包
? javax.swing
Swing组件和实用工具。
? javax.swing.border
Swing轻量组件的边框。
? javax.swing.colorchooser
JColorChooser的支持类 /接口。
? javax.swing.event
事件和监听器类。
? javax.swing.filechooser
JFileChooser的支持类 /接口。
? javax.swing.plaf
抽象类,它定义 UI代理的行为。
? javax.swing.plaf.basic
实现所有标准界面样式公共功能的基类。
? javax.swing.plaf.metal
用户界面代理类,它们实现 Metal界面样式。
? javax.swing.plaf.multi
用户界面代理类,它们可以用来实现两个或
以上的界面样式。
? javax.swing.table
JTable组件的支持类。
? javax.swing.text
支持文档的显示和编辑。
? javax.swing.text.html
支持显示和编辑 HTML文件。
? javax.swing.text.html.parser
html文件的分析器类。
? javax.swing.text.rtf
支持显示和编辑 RTF文件。
? javax.swing.tree
JTree组件的支持类。
? javax.swing.undo
支持取消操作。
? com.sun.java.swing.plaf.motif
用户界面代理类,它们实现 Motif界面样式。
? com.sun.java.swing.plaf.windows
用户界面代理类,它们实现 Mindows界面样
式。
? com.sun.java.swing.plaf.gtk
用户界面代理类,它们实现 GTK界面样式。
2012-3-7 Java面向对象程序设计教程 13
JComponent类的继承关系
继承关系
???????
java.lang.Object java.awt.Component java.awt.Container java.swing.JComponent Swing组件
Java的 GUI部件
都是 Component,
都有 paint、
repaint,update
方法。
Container是一个集
合,里面放了各种
的 GUI组件,而我
们常用的内容面板
Contentpane就是
一个 Container对象。
J2SDK中的
Component、
Container、
JComponet的方法
是所有 Swing组件
共有的。
2012-3-7 Java面向对象程序设计教程 14
JComponent类的优点
? 继承于 AWT容器,所以 Swing组件具有容器特性。
? 插入式界面样式或自定义 Look and Feel外观。
? 和 Windows一样的快捷键。
? 通用事件处理方法。
? 组件的简短描述(通过调用停留提示工具)。
? 根据不同国别进行本地化处理( Localization)。
2012-3-7 Java面向对象程序设计教程 15
Swing组件
? Swing包含 250多个类,是组件和支持类的
集合。
? Swing组件除了提供替代 AWT重量组件的
轻量组件外,还提供了大量有助于开发 GUI
的附加组件,如表格、树、定制对话框等。
? 为了把 UI组件和支持类分开,Swing组件
名字以, J”开头。
? 参见表 9.2, 9.3
2012-3-7 Java面向对象程序设计教程 16
支持 Drag and Drop的 Swing组件
组件 拖拷贝 拖移动 放操作 剪切 复制 粘贴
JColorChooser √ √
JEditorPane √ √ √ √ √ √
JfileChooser √ √
JFormattedTextField √ √ √ √ √ √
JList √ √
JPasswordField N/A N/A √ N/A N/A √
JTable √ √
JTextArea √ √ √ √ √ √
JTextField √ √ √ √ √ √
JTextPane √ √ √ √ √ √
JTree √ √
注,N/A为 Not Available,无效
举例,LabelDnD.java
2012-3-7 Java面向对象程序设计教程 17
Java 2D API中的包
? java.awt.color
颜色和颜色空间。
? java.awt.font
2D API字体软件包。
? java.awt.geom
2D API几何软件包。
? java.awt.print
支持打印 2D API。
? com.sun.image.codec.jpeg
JPEG图像处理工具包。
? java.awt.image.renderable
图像渲染处理工具包。
? 举例,LineArtDemo.java
2012-3-7 Java面向对象程序设计教程 18
Java Accessibility
? Accessibility就是一个很有用的辅助技术或系统,帮助那
些特殊人群使用用户界面,例如盲人或无法操作鼠标键盘
的人。
? 辅助系统包括屏幕阅读器,屏幕放大器和语音识别系统。
它还提供了一个接口,允许辅助技术与 JFC和 AWT组件互
动和通信。
9.2 应用程序和小程序界面图形化
2012-3-7 Java面向对象程序设计教程 20
Swing基本容器的组成
2012-3-7 Java面向对象程序设计教程 21
根面板 JRootPane类的组成
组件 类型 描述
glassPane JPanel 玻璃面板
layeredPane JLayeredPane 层序面板
ContentPane JPanel 内容面板
menuBar JMenuBar 菜单栏
2012-3-7 Java面向对象程序设计教程 22
内容面板
? 内容面板是小程序和应用程序的应用基础,是
JApplet和 JFrame等基本容器类用来管理组件的
代理。
? 我们在添加内容的时候,事实上是把内容加到这
些根面板的成员中去,而不是直接加到根面板对
象中。
? 其中最常用的是在自定义类(一般扩展 JApplet或
JFrame类)中把组件加入容器的内容面板,而不
是把它们直接加入根面板对象中,
? 我们定义放置组件的容器时调用的是
getContentPane方法,而并没有 getRootPane
方法。
2012-3-7 Java面向对象程序设计教程 23
操作内容面板
? 如果有 JRootPane类的实例 rootPane
? 添加组件 child到该容器的语句类似于
rootPane.getContentPane().add(child);
? 把包含组件的面板 myPane交由 rootPane的内容
面板进行展示的组件,那么语句类似
rootPane.setContentPane(myPane);
? 如果要改变组件的布局,实际上我们也是要操作
内容面板,这个语句如下,
rootPane.getContentPane().setLayout(new XXXLayout());
不是
rootPane.add(child);
2012-3-7 Java面向对象程序设计教程 24
JApplet类和 Swing小程序
? 我们把组件加在 JApplet对象的内容面板中,而不
是直接在 JApplet对象上。
? 我们在内容面板中设置布局管理器,而不是直接
在 JApplet对象上。
? 对 JApplet对象的内容面板来说,默认的布局管理
器是 BorderLayout。这有别于 Applet类的默认
管理器为 FlowLayout。
? 在扩展 JApplet的自定义类中,我们通常把组件的
初始化放在 init方法中实现。
? 小程序的典型例子,AppletGUI.java
2012-3-7 Java面向对象程序设计教程 25
讨论,AppletGUI.java
如果把
public void init(){
c=getContentPane();
Icon icon=new
ImageIcon(″swing.gif″);
label=new JLabel(″Swing标签 ″,
icon,
SwingConstants.CENTER
);
c.add(label,
BorderLayout.CENTER);
}
改为
public void init(){
JPanel panel=new JPanel();
Icon icon=new
ImageIcon(″swing.gif″);
label=new JLabel(″Swing标签 ″,
icon,
SwingConstants.CENTER
);
panel.add(label);
}
? 进一步完成程序,使得程序中
label组件的内容也能显示出来,
并且布局和原程序一致。
2012-3-7 Java面向对象程序设计教程 26
JFrame类和 Swing应用程序
? JFrame扩展了 java.awt.Frame类,它是 Swing
的最高层容器之一,拥有与 JApplet相似的特性。
不同之处在于它是用来支持应用程序而不是小程
序,而且,我们通常把组件的初始化代码块放在
扩展 JFrame的自定义类的构造方法中。
? Swing应用程序最高层容器往往扩展 JFrame类。
因此,我们应该关心的是把希望展示的组件添加
到 JFrame扩展类的实例的内容面板中。
? 举例,ApplicationGUI.java
2012-3-7 Java面向对象程序设计教程 27
结合小程序和应用程序的例子
? 结合 Swing的小程序和应用程序意味这该类编译
后既可以嵌入浏览器中执行,又可以通过 java执
行引擎引导执行。
? 为了利用好小程序可以在浏览器中自动加载执行,
我们通常会使这样的类直接扩展 JApplet类,然后
在 main方法中创建一个 JFrame外层面板框架,
并把自定义类的一个实例的内容面板传递给这个
JFrame对象的内容面板。
? 举例,AnAGUI.java
9.3 AWT的组件布局管理模型
2012-3-7 Java面向对象程序设计教程 29
基于策略模式的布局管理模型
? 定义了组件、容器和布局管理器之间的关系。
? 定义一个算法集并把这个算法封装在一个类里的
技术称为策略模式( Strategy pattern)。
? 一个容器中的组件很可能经历一个尺寸变化和移
动的过程。容器把对组件的布置 —— 整形和定
位 —— 授权给一个布局管理器。不同的布局管理
器使用不同的算法布置组件,容器可以通过使用
适当的布局管理器自由选择布置算法。
2012-3-7 Java面向对象程序设计教程 30
容器的授权管理及布局管理器的策略模式
2012-3-7 Java面向对象程序设计教程 31
组件、容器和布局管理器之间的关系
? 一个组件对象只能位于一个容器中。
? 容器知道如何添加和删除组件。
? 当我们为一个容器添加或删除组件时,调用容器
的 validate方法时变化显示出来。
? 容器不知道如何去做布局管理。
? 当容器改变大小或 validate方法被调用时,布局
管理器能自动调整容器的布局。
? 容器的布局策略可以在运行时调整。
? 布局管理器能重新计算布局,最上层容器框架的
setVisible方法负责调用 validate方法。
2012-3-7 Java面向对象程序设计教程 32
容器
? 每个容器都访问一个布局管理器,该布局管理器有责任对容器中
的组件进行定位和整形。
? 布局管理器由 setLayout方法设定。如果没有对 setLayout方法的
调用,那么默认的布局管理器就被使用。
? setLayout方法的基本形式如下,
public void setLayout(LayoutManager mgr)
设置当前容器的布局管理器类。
? 如果在运行时利用 setLayout方法改变一个容器的布局,布局管
理器并不会自动更新,需调用 validate方法(推荐),
public void validate()
有效化一个容器及其组件。
? 另外,doLayout方法也可以用来更新布局管理,
public void doLayout()
使容器更新布局。
2012-3-7 Java面向对象程序设计教程 33
布局管理器类举例
? FlowLayout类,FlowLayoutDemo.java
? BorderLayout类,BorderLayoutDemo.java
? GridLayout类,GridLayoutDemo.java
? CardLayout类,CardLayoutDemo.java
? BoxLayout类,BoxLayoutDemo.java
? GridBagLayout类:
GridBagLayoutDemo.java
? SpringLayout类,SpringLayoutDemo.java
? 组合应用布局管理器:
EmbeddedLayoutDemo.java
9.4 AWT的事件处理模型
2012-3-7 Java面向对象程序设计教程 35
基于观察者模式的事件处理模型
? 观察者模式( Observer pattern)定义了一种一对多的
依赖关系,让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态上发生变化时,会通知所有观察者对
象,使它们能够自动更新自己。
? 授权事件模型包括三部分来处理事件:事件源,事件和监
听器。
? 事件源是任何的用户界面组件,例如按钮,文本框,滚动条等等。
? 事件都继承自 java.util.EventObject类。
? 事件监听器是一个实现事件接听器接口的对象,而这个接口又继 承自 java.util.EventListener接口。在监听器类中的方法包含了
一些功能,当相应的用户界面组件被调用时就需要执行这些功能。
? 事件源产生并触发事件,事件一直传播到相应的事件监听
器,然后监听器调用特定的方法处理事件。
2012-3-7 Java面向对象程序设计教程 36
基于观察者模式的事件处理授权模型
2012-3-7 Java面向对象程序设计教程 37
Java事件处理过程
2012-3-7 Java面向对象程序设计教程 38
事件源与监听器
? 为了接受所产生的事件,监听器对象需要与事件源注册,
以确保监听器被调用。
? 事件源注册操作可以通过 setXXXListener或
addXXXListener方法进行,其中的, XXX”用来指某个
具体的事件类型。
? 相对而言,addXXXListener方法用得更多些,因为它可
以从事件源注册多个事件监听器。
? 可通过 removeXXXListener方法把监听器从事件源列表
上删除监听器,以从事件源断开监听器。但是,如果某个
类型的多个监听器向相同一个组件注册,虽然看起来通知
的顺序应该符合监听器被加入到组件中的顺序,但这样的
顺序是不确定的。
2012-3-7 Java面向对象程序设计教程 39
事件类
? 事件类代表事件本身。从本质上来说,它们就是
从事件源传播到任何感兴趣的事件监听器对象的
信息包。
? 每个事件对象包含有关事件源的信息。事件也可
能含有附加信息,包括:事件类型、改变了的值、
事件期间任何单击的鼠标按钮等等。
? 事件通常由系统生成,但是事件类提供创建事件
对象的公共构造方法,可以使用事件生命周期的
处理方法来分派这些用户生成的事件。
? 事件类构架可用于创建用户定义的事件的出发点。
2012-3-7 Java面向对象程序设计教程 40
Java事件的分类
? 低层事件 就是那些任何组件类型都能生成的事件。
低层事件的例子可以是键盘或鼠标事件。
从组件维护的监听器列表添加或删除低层监听器的方法
( addXXXListencr和 removeXXXListener方法)定义
在 Component和 JComponent类内。
? 高层事件(或者说语义事件) 是组件特定的事件。
高层事件只由 GUI组件的一小部分子集生成。例如,只有
实现 Adjustable接口的组件,比如 JScrollBar,才能生成
AdjustmentEvent对象。
从事件源监听器列表添加或删除高层事件监听器的方法一
般定义在生成事件的类内。例如,JButton能够生成
ActionEvent对象。 addActionListener和
removeActionListener方法定义在 JButton类内。
2012-3-7 Java面向对象程序设计教程 41
通常使用的事件监听器接口及其方法
接 口 描 述
ActionListener 定义了 1个接受动作事件的方法
AdjustmentListener 定义了 1个接受调整事件的方法
ComponentListener 定义了 4个方法来识别何时隐藏、移动、改变大小、显示组件
ContainerListener 定义了 2个方法来识别何时从容器中加入或除去组件
FocusListener 定义了 2个方法来识别何时组件获得或失去焦点
ItemListener 定义了 1个方法来识别何时项目状态改变
KeyListener 定义了 3个方法来识别何时键按下、释放和键入字符事件
MouseListener 定义了 5个方法来识别何时鼠标单击,进入组件,离开组件,按下和释放事件
MouseMotionListener 定义了 2个方法来识别何时鼠标拖动和移动
TextListener 定义了 1个方法来识别何时文本值改变
WindowListener 定义了 7个方法来识别何时窗口激活、关闭、失效、最小化、还原、打开和退出
2012-3-7 Java面向对象程序设计教程 42
常用的事件、事件监听器及其支持的事件源组件
事件、监听器及其
addXXXListener,removeXXXListener方法
支持事件的组件
ActionEvent
ActionListener
addActionListener(ActionListener l)
removeActionListener(ActionListener l)
JButton,JList,JTextField,JMenuItem及其
扩展类,包括 JCheckBoxMenuItem,JMenu、
JpopupMenu
AdjustmentEvent
AdjustmentListener
addAdjustmentListener(AdjustmentListener l)
removeAdjustmentListener(AdjustmentListener l)
JScrollbar及所有实现 Adjustable接口的类
ComponentEvent
ComponentListener
addComponentListener(ComponentListener l)
removeComponentListener(ComponentListener l)
Component及其扩展类,包括 JButton、
Canvas,JCheckBox,JComboBox、
Container,JPanel,JApplet,JScrollPane、
Window,JDialog,JFileDialog,JFrame、
JLabel,JList,JScrollbar,JTextArea、
JTextField
2012-3-7 Java面向对象程序设计教程 43
常用的事件、事件监听器及其支持的事件源组件
事件、监听器及其
addXXXListener,removeXXXListener方法
支持事件的组件
ContainerEvent
ContainerListener
addContainerListener(ContainerListener l)
removeContainerListener(ContainerListener l)
Container及其扩展类,包括 JPanel,JApplet、
JScrollPane,Window,JDialog,JFileDialog、
JFrame
FocusEvent
FocusListener
addFocusListener(FocusListener l)
removeFocusListener(FocusListener l)
Component及其扩展类
KeyEvent
KeyListener
addKeyListener(KeyListener l)
removeKeyListener(KeyListener l)
Component及其扩展类
MouseEvent
MouseListener
addMouseListener(MouseListener l)
removeMouseListener(MouseListener l)
Component及其扩展类
2012-3-7 Java面向对象程序设计教程 44
常用的事件、事件监听器及其支持的事件源组件
事件、监听器及其
addXXXListener,removeXXXListener方法
支持事件的组件
MouseEvent
MouseMotionListener
addMouseMotionListener(MouseMotionListener l)
removeMouseMotionListener(MouseMotionListener l)
Component及其扩展类
WindowEvent
WindowListener
addWindowListener(WindowListener l)
removeWindowListener(WindowListener l)
Window及其扩展类包括 JDialog,JFileDialog、
JFrame
ItemEvent
ItemListener
addItemListener(ItemListener l)
removeItemListener(ItemListener l)
JCheckBox,JCheckBoxMenuItem、
JComboBox,JList及实现 ItemSelectable接口
的类
TextEvent
TextListener
addTextListener(TextListener l)
removeTextListener(TextListener l)
JTextComponent及其扩展类,包括 JTextArea、
JTextField
2012-3-7 Java面向对象程序设计教程 45
适配器类实现的监听器接口
适配器类 监听器接口
ComponentAdapter ComponentListener
ContainerAdapter ContainerListener
FocusAdapter FocusListener
KeyAdapter KeyListener
MouseAdapter MouseListener
MouseMotionAdapter MouseMotionListener
WindowAdater WindowListener
举例,WindowListenerDemo.java, WindowAdapterDemo.java
2012-3-7 Java面向对象程序设计教程 46
创建事件监听器对象,
由当前 GUI主类实现
? 在这种方法,有时也称为自我监听,就是用组件
实现监听接口并实现接口内的方法,需要注意的
是这里的组件经常为容器。
? 优点:因为事件处理代码包含在 GUI代码内,事
件处理方法能自动调用 GUI的私有成员。
? 缺点:当有大量的 GUI组件同时需要把事件送到
同样的接口时,就可能产生混乱。
? 举例,MainClassDemo.java
2012-3-7 Java面向对象程序设计教程 47
创建事件监听器对象,
定义成独立的外部类
? 这种方法把事件处理代码和 GUI代码分离开
来了。事件监听器可以作为单独类来实现。
? 这种方法的优点为,事件处理代码从 GUI代
码中完全剥离,成为一个独立的类,增强
了可读性。而且在事件处理程序不需要调
用 GUI私有成员的情况下,也是很有用的。
? 举例,OuterClassDemo.java
2012-3-7 Java面向对象程序设计教程 48
创建事件监听器对象,
定义成内部类
? 这是方法 1和方法 2的结合。
? 这种方法的优点是,事件处理程序可以调
用外部类的私有成员,并且允许事件处理
模块化。
? 举例,InnerClassDemo.java
2012-3-7 Java面向对象程序设计教程 49
创建事件监听器对象,
定义成匿名内部类
? 实现事件监听器最简洁的方法。
? 它的优点就是处理简单的事件特别有用;
而且,因为匿名类的定义在事件源注册时
一起完成,我们更容易看出事件源关心的
事件类型。
? 它的缺点是当有较多的同类型事件监听器
对象时,重复的代码也比较多。
? 举例,AnonymousClassDemo.java
? 综合演示例子,EventProcessing.java