AWT编程

Java使用AWT和Swing类完成图形用户界面编程,事件处理负责让程序可以响应用户的动作。当使用AWT来编写图形界面应用时,程序仅指定了界 面组件的位置和行为,并未提供真正的实现,JVM调用操作系统本地的图形界面来创建和平台一致的对等体。

AWT编程中有两个基类:

1)Component:代表一个能以图形化方式显示出来,并可与用户交互的对象

2)MenuComponent:代表了图形界面的菜单组件。它们都继承于Object类。

Frame代表常见的窗口,它是Window类(Window是Container是Component是Object的子类)的子类,具有如下几个特征:

1)Frame对象有标题,允许通过拖拉来改变窗口的位置、大小

2)初始化时为不可见,可用setVisible(true)使其显示出来

3)默认使用BorderLayout作为其布局管理器

Panel是一个典型的容器,存在的意义在于为其它组件提供空间,具有如下几个特点:

1)可作为容器来盛装其它组件,为放置组件提供空间

2)不能单独存在,必须放置到其它容器中

3)默认使用FlowLayout作为其布局管理器

ScrollPane是一个带滚动条的容器,默认使用BorderLayout作为其布局管理器,ScrollPane通常用于盛装其它容器,所以通常不允许改变ScrollPane的 布局管理器

布局管理器

为了使生成的图形用户界面具有良好的平台无关性,Java语言中,提供了布局管理器这个工具来管理组件在容器中的布局,而不使用直接设置组 件位置和大小的方式。所有的AWT容器都有默认的布局管理器,如果没有为容器指定布局管理器,该容器使用默认的布局管理器。为容器指定布 局管理器通过调用容器对象的setLayoutManager(LayoutManager lm)方法来完成。

AWT提供了FlowLayout、BorderLayout、GridLayout、GridBigLayout、CardLayout 5个常用的布局管理器,Swing还提供了一个BoxLayout布局管理器

1、FlowLayout布局管理器(有对齐方式)

默认情况下,FlowLayout布局管理器从左向右排列所有组件,遇到边界就会折回下一行重新开始。构造器可以指定对齐方式(从左向右、从中间向两边、从右向左)、水平间距、垂直间距

Panel和Applet默认使用FlowLayout布局管理器。f.pack()方法是Window容器提供的一个方法,该方法用于将容器调整到最佳大小

2、BorderLayout布局管理器(有东、南、西、北、中五个区域)

BorderLayout将容器分为EAST、SOUTH、WEST、NORTH、CENTER五个区域,普通组件可以被放置在这五个区域中的任何一个。使用BorderLayout 有如下两个注意点:

1)当向使用该布局管理器的容器中添加组件时,需要指定要添加到哪个区域里。如果没有指定要添加到哪个区域里,则默认添加到中间区域里。

2)如果向同一个区域中添加多个组件时,后放入的组件会覆盖前面的组件

Frame、Dialog、ScrollPane默认使用BorderLayout布局管理器

BorderLayout最多只能放五个组件,但可以放少于五个。如果某区域没有放置组件,并不会出现空白,旁边区域的组件会自动占据该区域。因为容器也是一个组件,所以我们可以先向Panel里添加多个组件,再把Panel添加到BorderLayout布局管理器中。从而让实际组件个数远远超过5个。

3、GridLayout布局管理器(有行数、列数,new时需指定)

将容器分割成纵横线分割的网格,每个网格所占的区域大小相同。添加组件时,默认从左向右,从上向下依次添加到每个网格中。与FlowLayout 不同的是,放在GridLayout布局管理器中的各组件的大小由组件所处的区域来决定(每个组件将自动涨大到占满整个区域) --计算器。。。

4、GridBagLayout布局管理器(无参构造器)

功能最强大、但也是最复杂的布局管理器。与GridLayout不同的是:一个组件可以跨越一个或多个网格,并可以设置各网格的大小互不相同,从 而增加了布局的灵活性。

为了处理GridBagLayout中GUI组件的大小、跨越性,Java提供了GridBagConstraints对象,该对象与特定的GUI组件关联,用于控制该GUI组件的大 小、跨越性。使用GridBagLayout布局管理器的步骤如下:

1)创建GridBagLayout布局管理器,并指定GUI容器使用该布局管理器,如下代码:

GridBagLayout gb = new GridBagLayout();

constainer.setLayout(gb);

2)创建GridBagConstraints对象,并设置该对象的相关属性(用于设置受该对象控制的GUI组件的大小、跨越性等)--属性非常多。。。

GridBagConstraints gbc = new GridBagConstraints();

3)调用GridBagLayout对象的方法来建立GridBagConstraints对象和受控制组件之间的关联,如:

gb.setConstraints(c , gbc);

4)添加组件,与采用普通布局管理器添加组件的方法完全一样,如:

constainer.add(c);

5、CardLayout布局管理器(好像一副扑克牌)

以时间而非空间来管理它里面的组件,它将加入容器的所有组件看成一叠卡片,每次只有最上面的那个Component才可见。包含以下方法:

first(Container parent);

last(Container parent);

previous(Container parent);

next(Container parent);

show(Container parent , String name); 显示容器中指定名字的卡片

6、绝对定位

采用绝对定位的步骤如下:

1)将Container的布局管理器设成null:setLayout(null);

2)往容器中加组件的时候,先调用setBounds()或setSize()方法来先设置组件的大小、位置,或者直接创建GUI组件时通过构造参数指定该组件的大 小、位置,然后将该组件添加到容器中

使用绝对定位确实非常灵活,而且很简捷,但这种方式是以丧失跨平台特性作为代价的

7、BoxLayout布局管理器

GridBagLayout布局管理器虽然功能强大,但它实在太复杂了,所以Swing引入了一个新的布局管理器:BoxLayout。可以在垂直和水平两个方向上摆放GUI组件。构造器:BoxLayout(Container target , int axis); 按axis方向排列

BoxLayout通常和Box容器结合使用,Box是一个特殊的容器,它有点像Panel容器,但该容器默认使用BoxLayout布局管理器,Box提供了如下两个静 态方法来创建Box对象:

createHorizontalBox:创建一个水平排列组件的Box容器

createVerticalBox:创建垂直排列组件的Box容器

AWT常用组件

AWT组件需要调用运行平台的图形界面来创建和平台一致的对等体,所以AWT只能使用所有平台都支持的公共组件,所以AWT只提供了一些常用 的GUI组件

1、基本组件

AWT提供了如下基本组件:

Button:按钮,可接收单击操作

Canvas:用于绘图的画布

Checkbox:复选框组件(当成组时变成单选框组件)

CheckboxGroup:用于将多个Checkbox组成一组,一组中将只有一个可以被选中,即全部变成单选框组件

Choice:下拉框选择,要添加下拉框选项

Frame:窗口,在GUI程序里通过该类创建窗口

Label:标签类,用于放置提示性文本

List:列表框选择,可以添加多条项目,指定true时可以选择多项

Panel:不能单独存在的基本容器类,必须放到其它容器中

TextArea:多行文本域,可指定行,列

TextField:单行文本框,可指定列

Scrollbar:滑动条

ScrollPane:带水平及垂直滚动条的容器

2、对话框

对话框是Window类的子类,是一个容器类,属于特殊组件。对话框也是可以独立存在的顶级窗口,因此用法与普通窗口用法几乎完全一样,但 有两点需要注意:

1)对话框通常依赖于其它窗口,就是通常有一个parent窗口。

2)对话框有非模式和模式两种,模式对话框总是位于它依赖的窗口之上,在模式对话框被关闭之前,它依赖的窗口无法获得焦点

有多个重载的构造器,可能有多个参数

Dialog有一个子类:FileDialog,代表一个文件对话框,用于打开或者保存文件,也提供了几个构造器,分别可支持parent、title和mode三个构造参 数,mode用于指定该窗口用于打开文件还是保存文件,参数值:FileDialog.LOAD、FileDialog.SAVE

FileDialog不能指定是模式对话框还是非模式对话框,因为FileDialog依赖于运行平台的实现,如果运行平台的文件对话框是模式的,那么FileDialog 也是模式的,否则就是非模式的。提供了两个方法来获取被打开/保存文件的路径:

getDirectory():获取FileDialog被打开/保存文件的绝对路径

getFile():获取FileDialog被打开/保存文件的文件名

事件处理

在AWT编程中,所有事件的处理必须由特定对象(事件监听器)来处理,而Frame和组件本身并没有事件处理能力。

1、Java事件模型的流程

为了使图形界面能够接收用户的操作,必须给各个组件加上事件处理机制,在事件处理的过程中,主要涉及到3类对象:

1)Event Source(事件源):事件发生的场所,通常就是各个组件,如按钮、窗口、菜单等。最容易创建,只需要new来创建AWT组件。

2)Event(事件):事件封装了GUI组件上发生的特定事情(通常就是一次用户操作),如果程序需要获得GUI组件上所发生事件的相关信息,都 通过Event对象来取得。事件的产生无须程序员关心,它是由系统自动产生的。

3)Event Listener(事件监听器):负责监听事件源所发生的事件,并对各种事件作出响应处理。实现事件监听器是整个事件处理的核心。

当用发生动作时,这些动作会激发一个相应的事件,该事件会由AWT封装成一个相应的Event对象,该事件就会触发事件源上注册的事件监听器 (特殊的Java对象),事件监听器调用对应的事件处理器(事件监听器里的实例方法)来做出相应的响应。--委派式事件处理方式

实现AWT事件处理机制的步骤如下:

1)实现事件监听器类,该事件监听器类是一个特殊的Java类,必须实现一个XxxListener接口

2)创建普通组件(事件源),创建事件监听器对象

3)调用addXxxListener方法将事件监听器对象注册给普通组件(事件源)。

2、事件和事件监听器

事件监听器必须实现事件监听器接口,AWT提供了大量的事件监听器接口用于实现不同类型的事件监听器,用于监听不同类型的事件。AWT的事 件类都是AWTEvent抽象类的子类(ActionEvent),它是java.util.EventObject类的子类。EventObject类代表更广义的事件对象,包括Swing组件上所 引发事件、数据库连接所引发的事情等。

AWT事件分为两大类:

1)低级事件:基于特定动作的事件,如鼠标的进入、点击、拖放等

2)高级事件:也称语义事件,依赖于触发此事件的类,如在TextField中按Enter键会触发ActionEvent事件,滑动滚动条会触发AdjustmentEvent事 件,选中项目列表的某一条会触发ItemEvent事件,以下类都是AWTEvent类的子类:

ActionEvent

ActionListener

ActionPerformed:按钮、文本框、菜单项被单击时触发,TextField中按Enter键触发

AdjustmentEvent

AdjustmentListener

adjustmentValueChanged:滑动条上移动位置调节数值时触发

ItemEvent

ItemListener

itemStateChanged:某项被选中或取消选中时触发

TextEvent

TextListener

textValueChanged:文本组件里的文本发生改变时触发

ActionEvent对象的getActionCommand方法,用于获取被单击按钮上的文本

3、事件适配器

事件适配器是监听器接口的空实现:事件适配器实现了监听器接口,并为接口里每个方法都提供了实现,这种实现是一种空实现。当需要创建监听器时,可以通过继承事件适配器,而不是实现监听器接口

监听器接口

事件适配器

ContainerListener

ContainerAdapter

FocusListener

FocusAdapter

ComponentListener

ComponentAdapter

KeyListener

KeyAdapter

MouseListener

MouseAdapter

MouseMotionListener

MouseMotionAdapter

WindowListener

WindowAdapter

可以看出:所有包含多个方法的监听器接口都有一个对应的适配器,但只包含一个方法的监听器接口则没有对应的适配器

4、事件监听器的实现形式

事件监听器是一个特殊的Java对象,实现事件监听器对象有如下几种形式:

1)内部类形式:将事件监听器类定义成当前类的内部类

2)顶级类形式:将事件监听器类定义成一个顶级类 --比较少见:不利于提高程序的内聚性;编程不够简洁

3)类本身作为事件监听器类:让当前类本身实现监听器接口或事件适配器。添加监听器对象时直接使用this作为事件监听器对象即可

4)匿名内部类形式:使用匿名内部类创建事件监听器对象。目前使用最广泛的事件监听器形式

AWT的菜单

1、菜单条、菜单和菜单项

AWT的菜单由如下几个类组合而成:

1)MenuBar:菜单条,菜单的容器

2)Menu:菜单组件,菜单项的容器。它是MenuItem的子类,所以可作为菜单项使用,形成二级菜单

3)PopupMenu:弹出式菜单,右键菜单组件,它是Menu的子类。pop.show(p, e.getX(), e.getY()) 显示右键菜单。

4)MenuItem:菜单项组件

5)CheckboxMenuItem:复选框菜单项组件,选择后会在前面打上勾,再次选择后会取消

6)MenuShortcut:菜单快捷键组件

添加菜单分隔符有两种方法:

1)调用Menu对象的addSeparator方法来添加菜单分隔线

2)添加new MenuItem("-")菜单项来添加菜单分隔线

2、右键菜单

右键菜单使用PopupMenu对象表示,创建右键菜单的步骤如下:

1)创建PopupMenu的实例

2)创建多个MenuItem的多个实例,依次将这些实例加入PopupMenu中

3)将PopupMenu加入到目标组件中

4)为需要出现上下文菜单的组件编写鼠标监听器,当用户释放鼠标松开mouseReleased时,e.isPopupTrigger()判断是鼠标右键触发,如:

在AWT中绘图

1、画图的实现原理

在Component类里提供了三个和绘图有关的方法:

1)paint(Graphics g):绘制组件的外观

2)update(Graphics g):调用paint方法,刷新组件外观

3)repaint():调用update方法,刷新组件外观

Container类中的update方法先以组件的背景色填充整个组件区域,然后调用paint方法重画组件;普通组件的update方法则直接调用paint方法

程序不应该主动调用组件的paint和update方法,这两个方法都是由AWT系统负责调用,如果程序希望AWT系统重新绘制该组件,调用该组件的 repaint方法即可,而paint方法和update方法通常用于被重写

2、使用Graphics类

Graphics是一个抽象的画笔对象,可以在组件上绘制丰富多彩的几何图形和位图。AWT专门提供一个Canvas类作为绘图的画布,程序可以通过创 建Canvas的子类,并重写它的paint方法来实现绘图

改变窗口大小,或者让窗口隐藏后重新显示,这些动作都会触发组件的update方法。

Java也可以开发一些动画。所谓动画,就是隔一定的时间间隔(通常小于0.1秒)重新绘制新的图像,两次绘制的图像之间差异较小,肉眼看起来 就成了所谓的动画。为了实现隔一定时间间隔就重新调用组件的repaint方法,可以借助于Swing提供的Timer类。Timer类是一个定时器,有个:

Timer(int delay,ActionListener listener):每隔delay毫秒,系统自动触发ActionListener监听器里的事件处理器(actionPerformed方法)需要 start和stop方法来进行启动和停止

游戏有轻微的闪烁,这是由于AWT组件的绘图没有采用双缓冲技术,当重写paint方法进行绘制图形时,所有图形都是直接绘制到GUI组件上的, 所以多次重新调用paint方法进行绘制会发生闪烁现象。使用Swing组件就避免这种闪烁,Swing组件没有提供Canvas对应的组件,使用Swing的 JPanel组件作为画布即可

处理位图

Graphics提供了drawImage方法绘制位图,该方法需要一个Image参数——它就代表了位图,通过该方法就可以绘制出指定位图。

1、Image抽象类和BufferedImage实现类

Image是一个位图,但它是一个抽象类,无法直接创建Image对象。为此提供了BufferedImage实现类,它是一个可访问图像数据缓冲区的Image实 现类

BufferedImage还提供了一个getGraphics()方法返回该对象的Graphics对象,从而允许通过该Graphics对象向Image中添加图形。

借助于BufferedImage的帮助,我们可以在AWT中实现缓冲技术:当我们需要向GUI组件上绘制图形时,不要直接绘制到该GUI组件上,而是先将图 形绘制到BufferedImage对象中,然后再调用组件的drawImage一次性的将BufferedImage对象绘制到特定的组件上。

2、使用ImageIO输入/输出位图

如果希望可以访问磁盘上的位图文件,例如GIF、JPG等格式的位图,则需要利用ImageIO工具类。ImageIO利用ImageReader和ImageWriter进行读写图形文件。通常程序无须关心该类底层的细节,只需要利用该工具类来读写图形文件即可。

ImageIO类并不能支持读写全部格式的图形文件,程序可以通过ImageIO类的静态方法来访问该类所支持读写的图形文件格式

剪贴板

AWT支持两种剪贴板:系统剪贴板和本地剪贴板

1、数据传递的类和接口

AWT中剪贴板相关操作的接口和类被放在java.awt.datatransfer包下

2、传递文本

提供了StringSelection类(为Transferable接口的实现)用于传输文本字符串,将一段文本内容(字符串对象)放进剪贴板中的步骤如下:

1)创建一个Clipboard实例,既可以创建系统剪贴板,也可以创建本地剪贴板,创建系统剪贴板通过如下代码:

private Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();

创建本地剪贴板通过如下代码:

private Clipboard clipboard = new Clipboard("cb");

2)将需要放入剪贴板中的字符串封装成StringSelection对象,如下:

StringSelection contents = new StringSelection(taCopy.getText());

3)调用剪贴板对象的setContents方法将StringSelection放进剪贴板中,如:

clipboard.setContents(contents, null);

从剪贴板中取出数据则比较简单,调用Clipboard对象的getData(DataFlavor flavor)方法即可取出剪贴板中指定格式的内容:

if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) {

try {

//取出剪贴板中内容

String content = (String)clipboard.getData(DataFlavor.stringFlavor);

taPaste.append(content);

} catch (Exception e) {

e.printStackTrace();

}

}

3、使用系统剪贴板传递图像

Transferable接口代表了可以放入剪贴板的接口,所以如果希望将图像放入剪贴板内,必须提供一个Transferable接口的实现类,该实现类其实很简单,它封装一个image对象,并且向外表现为imageFlavor的内容。

注:JDK为Transferable类中仅提供了一个StringSelection实现类,用于封装字符串内容。但JDK在DataFlavor类中提供了一个imageFlavor常量,用于代表图像格式的DataFlavor,并负责执行所有复杂操作,以便进行Java图像和剪贴板图像的转换

4、使用本地剪贴板来传递对象引用

本地剪贴板可以保存任何类型的Java对象,包括自定义类型的对象。为了将任意类型的Java对象保存到剪贴板中,DataFlavor里提供了一个javaJVMLocalObjectMimeType的常量,该常量是一个MIME类型字符串:

public static final String javaJVMLocalObjectMimeType = "application/x-java-jvm-local-objectref";

将Java对象放入本地剪贴板必须使用该MIME类型,该MIME类型表示仅将对象引用复制到剪贴板中。对象引用只有在同一个虚拟机中才有效,所以只能使用本地剪贴板。

注:本地剪贴板是虚拟机负责维护的内存区,因此本地剪贴板会随虚拟机的结束而销毁。因此一旦Java程序退出,本地剪贴板的内容将会丢失

5、通过系统剪贴板传递Java对象

系统剪贴板不仅支持传输文本、图像的基本内容,也可以传输支持序列化的Java对象和远程对象,复制到剪贴板中序列化的Java对象和远程对象可以使用另一个Java程序(不在同一个虚拟机内的程序)来读取。DataFlavor中提供了javaSerializedObjectMimeType、javaRemoteObjectMimeType两个字符串常量来表示序列化Java对象和远程对象的MIME类型。

你可能感兴趣的:(AWT编程)