Download presentation
Presentation is loading. Please wait.
1
第八讲 图形用户界面与事件处理 1、使用AWT(Abstract Window Toolkit)组件
2、包含组件的组件——组件容器(Container) 3、外观的管理与控制 4、事件与事件处理 5、AWT中的各种组件 6、组件的应用实例
2
图形用户界面 用户界面:用户与计算机进行交互的渠道,人(眼睛和手指…)和计算机(硬件和软件)的通信,协同完成一定任务。与计算机输入/输出过程都相关。 人的主体参与:接受信息、思考、决策、发出命令。 计算机软硬件参与的工作:进一步明确所要执行命令,执行计算,反馈信息。 命令行式全字符用户界面 图形用户界面:让计算机变得更加容易使用
3
图形用户界面 面向对象的图形用户界面:基于“面向对象”的思想互相交换信息,即尽可能在屏幕上用形象的图标和窗口等来代表有用的资源和可启用的对象。 图形界面对象:代表特定的软件、命令、过程、资源、提示信息等 图标(Icon) 窗口(Window) 菜单(Menu)/菜单项(Menu Item) 按钮(Button)、文本框(Label)、列表框(List)… ……
4
图形用户界面 图形界面编程的主要特征: 图形界面对象及其框架(图形界面对象之间的包含关系) 图形界面对象的布局(图形界面对象之间的位置关系)
图形界面对象上的事件响应(图形界面对象上的动作)
5
1、使用AWT(Abstract Window Toolkit)组件
通过图形用户界面(Graphical User Interface,GUI),用户和程序之间可以方便友好地进行交互。在Java语言中,Java的基础类(Java Foundation Classes,JFC)是开发GUI的API集,它包括以下几个部分: 抽象窗口工具包(AWT):Java开发用户界面最初的工具包,是建立JFC的主要基础; 2D API:实现高质量的二维图形; Swing组件:建立在AWT之上,新的、功能更强大的图形组件包; 可访问API:支持残疾用户的交互; ……
6
1、使用AWT(Abstract Window Toolkit)组件
java.awt及相关包中包含了一个完整的类集以支持GUI程序的设计,其中的类及相互关系可以用下图来描述(重量级构件): 事件类 字体类 Graphics Component 颜色类 布局管理类 java.lang.Object Checkbox Container Button … Window Panel Applet Dialog Frame List 图象类 菜单类
7
1、使用AWT(Abstract Window Toolkit)组件
Component类 java.awt包中最核心的类就是Component类,它是构成Java图形用户界面的基础,大部分组件都是由该类派生出来的。 Component类是一个抽象类,其中定义了组件所具有的一般功能:基本的绘画支持(paint, repaint, update等)、字体和颜色等外形控制(setFont, SetForeground等)、大小和位置控制(SetSize, SetLocation等)、图象处理(实现接口ImageObserver)以及组件状态控制(SetEnable, isEnable, isVisible, isValid等) ,……。 常见的组件包括:Button, Checkbox, CheckboxGroup, Choice, Label, List, Canvas, TextComponent, Scrollbar等。
8
1、使用AWT(Abstract Window Toolkit)组件
9
1、使用AWT(Abstract Window Toolkit)组件
Container类 Container类是由Component类派生出来的一种特殊类,用来表示各种GUI组件的容器,其主要功能包括: 组件的管理:方法add()可以向其中添加一个组件,remove()删除其中的一个组件,… 布局管理:每个Container类都和一个布局管理器相联,以确定其中组件的布局。 Container类可以通过setLayout()方法设置某种布局方式。 常见的Container类有:Frame, Panel, Applet等。
10
1、使用AWT(Abstract Window Toolkit)组件
菜单类 菜单类也是一种重要的图形组件,只不过菜单类并不是由一般的Component类派生的,而是从MenuComponent类继承得到的。
11
1、使用AWT(Abstract Window Toolkit) 组件
布局管理器类 Java中提供了各种布局管理器类来管理各种组件在容器中的放置状态,这些类都是实现了LayoutManager接口的。标准的布局管理器类有: FlowLayout BorderLayout GridLayout CardLayout GridBagLayout 还可以通过实现LayoutManager接口来定义自己的布局管理器。
12
1、使用AWT(Abstract Window Toolkit)组件
Graphics类 Graphics类是所有用来在组件上进行图形绘制时所使用的图形环境上下文的父类,它提供了对组件进行图形绘制的一般方法的接口,一个Graphics对象中封装了用来进行图形绘制时必须得状态信息,包括: 要绘制的组件对象 当前颜色 当前字体 当前逻辑点操作的功能(XOR和Paint) 当前XOR方式的替代颜色 ……
13
1、使用AWT(Abstract Window Toolkit)组件
Graphics类还提供了一系列的方法来绘制几何图形、文字、图象以及动画: Lines:drawLine() Rectangles:drawRect(), fillRect() 和 clearRect() Raised or lowered rectangles:draw3DRect() 和 fill3DRect() Round-edged rectangles:drawRoundRect() 和 fillRoundRect() Ovals:drawOval() 和 fillOval() Arcs:drawArc() 和 fillArc() Polygons :drawPolygon() 和 fillPolygon() Text :drawString() Image :drawImage() Animation :通过一个循环来完成
14
1、使用AWT(Abstract Window Toolkit)组件
事件类:描述各种事件的类,包括AWTEvent类及其子类、Event类。 字体类:用来表示字体的类,通过它可以在GUI中使用多种系统支持的字体。 图象类:用来表示与处理图象的类(GIF、JEPG)。 颜色类:封装了各种颜色。 其他类:光标类、各种几何类等 …… GUIWindow.java
15
1、使用AWT(Abstract Window Toolkit)组件
组件及其对等类(peers) java.awt.peer中有全部awt组件的对等对象的集合,每个对象都提供了机器相关基本的方法,awt中的组件使用这些方法来实现机器和操作系统无关的GUI。
16
javax.swing包中包含了存java的完整的类集以支持GUI程序的设计(轻量级构件)
1、使用AWT(Abstract Window Toolkit)组件 javax.swing包中包含了存java的完整的类集以支持GUI程序的设计(轻量级构件) java.lang.Object java.awt.Component java.awt.Container javax.swing.JComponent ......
17
javax.swing中的组件 1、使用AWT(Abstract Window Toolkit)组件 JLabel 显示一行文字,可带图标
JTextField 用户让用户输入一行文字的构件 JButton 用于点击执行命令 JCheckBox 标记状态 JRadioButton 标记多状态 JCombox 下拉列表框供选取 JList 一组列表项供选择
18
2、包含组件的组件——组件容器(Container)
一个Java的图形用户界面的最基本组成部分就是组件(Component),组件是一个可以以图形化的方式显示在屏幕上并能与用户进行交互的对象,比如Button, Checkbox, Choice, Label, List等。 组件不能独立地显示出来,必须将组件放在特定的对象中才能显示出来,这就是包含组件的组件——Container(容器)。容器Container是Component的子类,它本身也是一个组件,具有组件所有的性质。另外,它还具有容纳其他组件和容器的功能。
19
2、包含组件的组件——组件容器(Container)
列表 按钮 菜单 Container 另一个窗口 窗口,对话框 Component
20
2、包含组件的组件——组件容器(Container)
AWT使用Container类来定义最基本的组件容器,它有两个常用的子类:Window类和Panel类。 Window类还有两个子类: 定义对话框,用Dialog子类。Java还提了一个Dialog的子类——FileDialog,用它生成文件对话框。 定义一般意义的窗口,用Frame类。 Frame可以用其构造方法Fame(String)来生成,其标题由String参数指定。一个Frame刚被创建后,其初始大小为(0,0),而且是不可见的,所以为了使Frame显示出来,必须在程序中显式地设置一下它的大小。
21
2、包含组件的组件——组件容器(Container)
Panel可以使程序员更方便地组织自己的组件,得到赏心悦目的布局。 Panel可以使用构造方法Panel()生成,当一个Panel对象被创建后,必须放在Window和Frame中才能可见。使用add()方法就可以将Panel添加到其他容器中。 Applet是Panel的子类,因此在小应用程序里可以直接加入构件,而一般的应用程序必须先定义构件容器。小应用程序在浏览器中所显示的区域就是Panel,所占的尺寸就是缺省的Panel尺寸(浏览器本身也可以看作是一个容器)。
22
2、包含组件的组件——组件容器(Container)
图形用户界面程序的主体框架是Window类及其子类(Frame、Dialog、FileDialog),一个Window类及其子类的实例,是不能包含其他Window类及其子类的实例,但它可以弹出其他的Window类及其子类的实例(弹出新窗口)。 Panel是一个不可见的组件容器,它可以容纳不同的组件,包括Panel本身(即可以嵌套包含)。但最顶层的Panel必须放在一个窗口容器中,包含在其中的所有可见组件才能显示出来。Panel的主要作用就是为了更好地进行图形界面对象的布局。 列表 按钮 弹出菜单 Container 另一个 Panel Panel Component 窗口及其子类 菜单 新窗口 弹出
23
2、包含组件的组件——组件容器(Container)
Window Panel Component Frame Dialog FileDialog Applet Button List Checkbox Textfield
24
弹出新窗口 MyFrame.java public class MyFrame extends Frame {
public static void main(String args[]) MyFrame fr = new MyFrame("Frame and FileDialog Test"); fr.setSize(500,500); fr.setBackground(Color.blue); fr.setVisible(true); fr.showDialog(); } public MyFrame(String str) super(str); addWindowListener( new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); }); public void showDialog() FileDialog fd = new FileDialog(this, "FileDialog"); fd.setVisible(true); 弹出新窗口 MyFrame.java
25
窗口中包含Panel MyPanelInFrame.java
public class MyPanelInFrame extends Frame { public MyPanelInFrame(String str) super(str); addWindowListener( new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } }); public static void main(String args[]) MyPanelInFrame fr = new MyPanelInFrame("Panel in Frame"); Panel pan = new Panel(); fr.setSize(500,500); fr.setBackground(Color.green); fr.setLayout(null); pan.setSize(200,200); pan.setBackground(Color.yellow); pan.setLocation(100,100); Button b1 = new Button("Help"); Button b2 = new Button("Test"); pan.add(b1); pan.add(b2); fr.add(pan); fr.setVisible(true); 窗口中包含Panel MyPanelInFrame.java
26
3、外观的管理与控制 1 2 4 3 5
27
3、外观的管理与控制 为了使生成的图形用户界面具有良好的平台无关性,Java语言提供了布局管理器来管理组件在容器中的布局,而不使用直接设置组件的位置和大小的方式。每个容器都要一个布局管理器,容器中组件的大小和定位都由它来决定。当容器需要对某个组件进行定位时,就会调用其对应的布局管理器。 容器 布局管理器
28
3、外观的管理与控制 在程序中安排组件的位置和大小时,应注意:
容器中布局管理器负责各组件的大小和位置,用户无法在这种情况下设置组件的这些属性,如试图调用setLocation(), setSize(), setBounds()等。 如果用户确实需要自己设置组件的大小和位置,则应取消该容器的布局管理器,方法为: setLayout(null) 但用户必须使用setLocation(), setSize(), setBounds()等方法为组件设置大小和位置,不过程序将系统相关。
29
3、外观的管理与控制 在容器中所有组件的布局都由布局管理器来控制,每个容器,如Panel、Windows或Frame都有各自缺省的布局管理器,程序员也可以在程序中指定一个新的布局管理器。 java.awt类包中包含五种布局管理器: FlowLayout:Panel和Applet的缺省布局管理器 BorderLayout:Window、Dialog和Frame的缺省布局管理器 GridLayout CardLayout
30
3、外观的管理与控制 ——FlowLayout
FlowLayout布局方式是将组件一排一排地依次放置,它自动调用组件的getPreferredSize()方法,使用组件的最佳尺寸来显示组件。当容器被重新设置大小后,则布局也会随之发生改变:各组件的大小不变,但相对位置会发生变化。 FlowLayout类有三种构造方法: public FlowLayout() 使用缺省居中对齐方式,组件间的水平和竖直间距为缺省值5个象素。 public FlowLayout(int alignment) 使用指定的对齐方式(FlowLayout.LEFT,FlowLayout.RIGHT,FlowLayout.Center),水平和竖直间距为缺省值5象素。 public FlowLayout(int alignment, int horizontalGap, int verticalGap) 使用指定的对齐方式,水平和竖直间距也为指定值。
31
FlowWindow.java public class FlowWindow extends Frame {
public FlowWindow() setLayout( new FlowLayout() ); setFont(new Font("Helvetica", Font.PLAIN, 14)); add(new Button("Button 1")); add(new Button("2")); add(new Button("Button 3")); add(new Button("Long-Named Button 4")); add(new Button("Button 5")); } public boolean handleEvent(Event e) if (e.id == Event.WINDOW_DESTROY) { System.exit(0); return super.handleEvent(e); public static void main(String args[]) FlowWindow window = new FlowWindow(); window.setTitle("FlowWindow Application"); window.pack(); window.show(); FlowWindow.java
32
3、外观的管理与控制 ——BorderLayout
BorderLayout布局方式提供了更复杂的布局控制方法,它包括5个区域:North, South, East, West和Center,其方位依据上北下南左西右东。当容器的尺寸发生变化时,各组件的相对位置不变,但中间部分组件的尺寸会发生变化,南北组件的高度不变,东西组件的宽度不变。 BorderLayout类有二种构造方法: public BorderLayout() 各组件间的水平和竖直间距为缺省值0个象素。 public BorderLayout(int horizontalGap, int verticalGap) 各组件间的水平和竖直间距为指定值。 North South West East Center
33
3、外观的管理与控制 ——BorderLayout
如果容器使用了BorderLayout布局方式,则用add()方法往容器中添加组件时必须指明添加的位置,否则组件将无法正确显示(不同的布局管理器,向容器中添加组件的方法也不同)。 add(“West”, new Button(“West”)); add(“North”, new Button(“North”)); add(new Button(“West”), BorderLayout.SOUTH); 若没有指明放置位置,则表明为默认的“Center”方位。 每个区域只能添加一个组件,若添加多个,则只能显示一个。如果想在一个区域添加多个组件,则必须先在该区域放一个Panel容器,再将多个组件放在该Panel容器中。 若每个区域或若干个区域没有放置组件,东西南北区域将不会有预留,而中间区域将置空。
34
BorderWindow.java public class BorderWindow extends Frame {
public BorderWindow() setLayout(new BorderLayout(5,5)); setFont(new Font("Helvetica", Font.PLAIN, 14)); add("North", new Button("North")); add("South", new Button("South")); add("East", new Button("East")); add("West", new Button("West")); add("Center", new Button("Center")); } public boolean handleEvent(Event e) if (e.id == Event.WINDOW_DESTROY) { System.exit(0); return super.handleEvent(e); public static void main(String args[]) BorderWindow window = new BorderWindow(); window.setTitle("BorderWindow Application"); window.pack(); window.show(); BorderWindow.java
35
3、外观的管理与控制 ——GridLayout
各组件的排列方式:从左到右,从上到下。 与BorderLayout类相类似,如果想在一个网格单元中添加多个组件,则必须先在该网格单元放一个Panel容器,再将多个组件放在该Panel容器中。
36
3、外观的管理与控制 ——GridLayout GridLayout类有三种构造方法: 在一行中放置所有的组件,各组件间的水平间距为0象素。
public GridLayout() 在一行中放置所有的组件,各组件间的水平间距为0象素。 public GridLayout(int rows, int cols) 生成一个rows行,cols列的管理器,最多能放置rows*cols个组件。 rows或cols可以有一个为0。若rows为0,这表示每行放置cols个组件,根据具体组件数,可以有任意多行;若cols为0,这表示共有rows行,根据具体组件数,每行可以放置任意多个组件。 组件间的水平和竖直间距为0象素。 public GridLayout(int rows, int cols, int horizontalGap, int verticalGap ) 各组件间的水平和竖直间距为指定值。
37
GridWindow.java public class GridWindow extends Frame {
public GridWindow() setLayout(new GridLayout(0,2)); setFont(new Font("Helvetica", Font.PLAIN, 14)); add(new Button("Button 1")); add(new Button("2")); add(new Button("Button 3")); add(new Button("Long-Named Button 4")); add(new Button("Button 5")); } public boolean handleEvent(Event e) if (e.id == Event.WINDOW_DESTROY) { System.exit(0); return super.handleEvent(e); public static void main(String args[]) GridWindow window = new GridWindow(); window.setTitle("GridWindow Application"); window.pack(); window.show(); GridWindow.java
38
3、外观的管理与控制 ——CardLayout
CardLayout布局方式可以帮助用户处理两个或更多的组件共享同一显示空间。共享空间的组件之间的关系就像一摞牌一样,它们摞在一起,只有最上面的组件是可见的。 CardLayout可以象换牌一样处理这些共享空间的组件:为每张牌定义一个名字,可按名字选牌;可以按顺序向前或向后翻牌;也可以直接选第一张或最后一张牌。 public void show(Container parent, String name) public void next(Container parent) public void previous(Container parent) public void first(Container parent) public void last(Container parent) 其中,Container是拥有该CardLayout布局管理器的容器。
39
3、外观的管理与控制 ——CardLayout CardLayout类有二种构造方法: 组件距容器左右边界和上下边界的距离为缺省值0个象素。
public CardLayout() 组件距容器左右边界和上下边界的距离为缺省值0个象素。 public CardLayout(int horizontalGap, int verticalGap) 组件距容器左右边界和上下边界的距离为指定值。 与BorderLayout类和GridLayout类相类似,每张牌中只能放置一个组件,如果想在一张牌放置多个组件,则必须先在该牌放一个容器,再将多个组件放在该容器中。 采用CardLayout布局方式时,向容器中添加组件时可以为组件取一个名字,以供更换显示组件时使用: add(String, Component);
40
3、外观的管理与控制 ——CardLayout North Panel1 Choice Frame: Border Panel2: Card
Button or Textfield Center CardWindow.java
41
4、事件与事件处理 所谓事件,就是发生在用户界面上的用户交互行为而产生的一种效果,如鼠标的各种动作、键盘的操作以及发生在组件上的各种动作,因此事件一般也分为三种类型:键盘事件、鼠标事件以及组件的动作事件(对鼠标或键盘事件在一定程度上进行了封装)。 每发生一个事件,程序都需要作出相应的响应,这称为事件处理。在JDK1.0和1.1中,事件表示以及事件的处理是采用不同的方式来完成的。
42
if( Ev.id == ACTION_EVENT ){…}
4、事件与事件处理 ——JDK1.0的事件处理 在JDK1.0中,所有事件都封装在一个单一的类java.awt.Event中,该类是从java.lang.Object直接继承而来。在Event中,提供了各种常量和变量来描述事件,包括事件的类型、事件的产生者、事件的内容、事件相关信息等,同时也提供了相关的方法来进一步获取事件相关信息。 例如,为了区分事件类型,需要用其事件分类标志变量id来判断事件是否属于动作事件: if( Ev.id == ACTION_EVENT ){…}
43
4、事件与事件处理 ——JDK1.0的事件处理 Event类的变量属性 Event Object arg int clickCount
int id int key int modifiers Object target int x int y long when Event类的变量属性 事件类型:如ACTION_EVENT、KEY_ACTION、 MOUSE_DOWN、MOUSE_ENTER、WINDOW_DISTORY等。 键值:如F1、DELETE、DOWN、ESCAPE等。
44
4、事件与事件处理 ——JDK1.0的事件处理 在JDK 1.0中,是采用一种叫做事件传递的机制来处理发生在用户界面上的事件。
在AWT组件中,都从Component中继承了与事件处理有关的方法: action(Event e, Object arg):处理动作事件 handleEvent(Event e):处理低级键盘事件和鼠标事件 每个组件都可以用上述方法处理发生在自己上面的事件,同时,也可以不作处理,而是交给包含它的容器去处理,并且可以一层一层往上传递,直到最顶层容器。不论哪种方法,都需要继承已有的AWT组件,生成其子类,在子类中重写上述方法来对事件进行处理。
45
如果不覆盖要处理的方法,则缺省的方法返回一个假值,通知系统没有处理事件
4、事件与事件处理 ——JDK1.0的事件处理 Event HandleEvent() MouseUp() MouseDown() MouseDrag() MouseMove() MouseEnter() MouseExit() keyDown() KeyUp() action() AWT组件 如果不覆盖要处理的方法,则缺省的方法返回一个假值,通知系统没有处理事件
46
4、事件与事件处理 ——JDK1.0的事件处理 ComponentEvent.java 在组件中处理自身的消息:继承组件
class MyButton extends Button { MyButton(String str) super(str); } public boolean action(Event e, Object arg) if( arg=="Test") System.out.println( "Button Test pressed."); else System.exit(0); return true; public class ComponentEvent { public static void main(String args[]) Frame fr = new Frame( "Component Event Test 1.0"); MyButton myB1 = new MyButton("Test"); MyButton myB2 = new MyButton("Exit"); fr.setLayout( new FlowLayout() ); fr.add(myB1); fr.add(myB2); fr.resize(200,200); fr.show(); } ComponentEvent.java 在组件中处理自身的消息:继承组件
47
4、事件与事件处理 ——JDK1.0的事件处理 将消息传递给组件的容器处理:继承容器 ContainerEvent.java
class MyFrame extends Frame { MyFrame(String str) super(str); } public boolean action(Event e, Object arg) if( arg=="Test") System.out.println( "Button Test pressed."); else System.exit(0); return true; public class ContainerEvent { public static void main(String args[]) MyFrame fr = new MyFrame( "Container Event Test 1.0"); Button B1 = new Button("Test"); Button B2 = new Button("Exit"); fr.setLayout( new FlowLayout() ); fr.add(B1); fr.add(B2); fr.resize(200,200); fr.show(); } ContainerEvent.java
48
4、事件与事件处理 ——JDK1.0的事件处理 handleEvent(Event e)方法一般用来处理低级键盘事件和鼠标事件,其缺省的处理方法为: public boolean handleEvent(Event evt) { switch(evt.id) case Event.MOUSE_ENTER: return mouseEnter(evt,evt.x,evt.y); case Event.MOUSE_EXIT: return mouseExit(evt,evt.x,evt.y); case Event.MOUSE_MOVE: return mouseMove(evt,evt.x,evt.y); case Event.MOUSE_DRAG: return mouseDrag(evt,evt.x,evt.y); case Event.MOUSE_UP: return mouseUp(evt,evt.x,evt.y); case Event.MOUSE_DOWN: return mouseDown(evt,evt.x,evt.y); case Event.KEY_PRESS: case Event.KEY_ACTION: return keyDown(evt,evt.key); case Event.KEY_RELEASE: case Event.KEY_ACTION_RELEASE: return keyUp(evt,evt.key); case Event.ACTION_EVENT: return action(evt,evt.arg); case Event.GOT_FOCUS: return gotFocus(evt,evt.arg); case Event.LOST_FOCUS: return lostFocus(evt,evt.arg); } return false;
49
4、事件与事件处理 ——JDK1.0的事件处理 可以看到,在JDK1.0中,进行事件处理时一般都要继承已有的组件生成新的子类,并在在子类中重写action()和handleEvent()方法进行处理,或沿着组件层次传给上一级容器(此时容器类也一样要继承生成新的子类),若直到最顶层容器仍没有处理,则合理遗弃。 在第一种方法中,需要为每一种AWT组件产生子类,处理起来很是麻烦。在第二种方法中,处理起来简单些(只需生成一个容器子类即可),但一个发生在按钮上的事件,处理它的action方法却属于包含按钮的父类容器,这不符合面向对象的设计原则,并且在事件传递的过程中可能会产生遗漏。 另外,JDK1.0没有事件过滤机制,事件一旦发生,都会自动传递给组件,不管组件是否需要处理它,这大大降低了程序的运行效率(尤其实鼠标移动这种高频事件)。 还有一点就是会使程序的结构不清晰,可读性差。
50
4、事件与事件处理 ——JDK1.1的事件处理 在JDK1.1中,对事件进行了分类,并且对发生在组件上的事件进行了过滤。所有事件都放在包java.awt.event中,这些事件都从java.util.EventObject而来,对于发生在组件上的事件,则由java.awt.event.AWTEvent派生,大致可分为以下十几类,同时又归为两大类: 低级事件: ComponentEvent, (ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent) HierarchyEvent,(组件层次) InputMethodEvent, (文本区内容) InvocationEvent, (线程调用) 高级事件(语义事件,一般的GUI编程,只需对这类事件进行处理即可) ActionEvent , AdjustmentEvent, ItemEvent, TextEvent,……
51
4、事件与事件处理 ——JDK1.1的事件处理 在JDK1.1中,事件处理模型将事件源(产生事件的组件)和对事件作出的具体处理(利用一种称为监听器[listener]的实体来对事件进行具体的处理)分开。 一般情况下,组件(事件源)都不处理自己的事件,而是将事件处理委托给外部的处理实体(监听器),这种事件处理模型称为事件的授权处理模型。不同的事件,可以交由不同类型的监听器去处理。 所有的组件都从Component类中继承了将事件处理授权给监听器的方法: addXXXListener(ListenerType listener) removeXXXListener(ListenerType listener)
52
4、事件与事件处理 ——JDK1.1的事件处理 ComponentEvent2.java
public class ComponentEvent2 { public static void main(String args[]) Frame fr = new Frame( "Component Event Test 1.1"); ButtonListener bl = new ButtonListener(); Button b1 = new Button("Test"); Button b2 = new Button("Exit"); b1.addActionListener(bl); b2.addActionListener(bl); fr.setLayout( new FlowLayout() ); fr.add(b1); fr.add(b2); fr.resize(200,200); fr.show(); } class ButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) if( e.getActionCommand()=="Test") System.out.println( "Button Test pressed."); } else System.exit(0); ComponentEvent2.java
53
actionPerformed(ActionEvent e)
4、事件与事件处理 ——JDK1.1的事件处理 Test Exit ActionEvent actionPerformed(ActionEvent e) Frame 事件源 监听器(ButtonListener) 首先,对于某种类型的事件XXXEvent,要想接收并处理该类事件,必须定义相应的事件监听器类,这个类需要实现针对该类事件的特定接口XXXListener。 其次,要实现该类中对事件处理的方法。 第三,对于事件源,必须使用addXXXListener(XXXListener)注册该类事件的监听器,以便当事件产生时,能够被监听器接收和处理。
54
4、事件与事件处理 ——JDK1.1的事件处理 JDK1.1事件处理模型中的监听器都是通过实现在包java.awt.event中提供的监听器接口来获得的。每种事件都对应有相应的监听器接口,事件的处理方法都已经在该接口中定义了。 interface XXXListener extends java.util.EventListener { public void XXXEventMethod( XXXEvent e); } 监听器接口定义 interface ActionListener extends java.util.EventListener { public void actionPerformed(ActionEvent e) } 监听器 接口 示例 interface KeyListener extends java.util.EventListener { public void keyPressed(KeyEvent e); public void keyReleased(KeyEvent e); public void keyTyped(KeyEvent e); }
55
4、事件与事件处理 ——JDK1.1的事件处理 各AWT组件所产生的事件:
Events Generated by AWT Components.htm 各AWT事件与其相应的监听器接口: Handling Standard AWT Events.htm
56
在一个监听器类中可以实现多个监听器接口,通过它可以同时监听同一个事件源上发生的多种事件,同时,通过事件可以获得事件的详细信息。
4、事件与事件处理 ——JDK1.1的事件处理 在一个监听器类中可以实现多个监听器接口,通过它可以同时监听同一个事件源上发生的多种事件,同时,通过事件可以获得事件的详细信息。 MultiListener.java
57
4、事件与事件处理 ——JDK1.1的事件处理 由于通过实现接口XXXListener来完成事件处理时,要同时实现该接口中的所有方法。通常我们只是需要对其中的某些方法做处理,而不想实现所有的无关方法。 因此,为了方便起见,JDK1.1为某些监听器接口提供了适配器类(XXXAdapter),当需要对某种事件进行处理时,只需让事件处理类继承事件所对应的适配器类,只重写需要关注的方法即可,而无关的方法就不必实现了。 适配器是一个类而不是接口,因而处理事件的类只能继承一个适配器。当该类需要处理多种事件时,通过继承适配器类的方式是不行的。但可以基于适配器类,用内嵌类(Inner Class)的方法来处理这种情况。 MultiListener1.java
58
5、AWT中的各种组件
59
5、AWT中的各种组件 按钮(Button) 复选框(Checkbox)
可点击的用户界面组件,当组件被点击是,产生AcitonEvent事件,可以用ActionListener来监听。 复选框(Checkbox) 提供简单的“on/off”开关,同时旁边还可以显示说明信息。当复选框状态发生变化时,会产生ItemEvent事件,可以用ItemListener来监听。 复选框组(CheckboxGroup)——单选框(Radio Button) 当多个复选框组成一组时,就形成了单选框。复选框组中的复选框之间是相互关联的,每次有且只有一个处于选中状态。 下拉式菜单(Choice) 在下拉式菜单中有多个选项,但每次只能选择一项。当选择发生时,会产生ItemEvent事件,可以用ItemListener来监听。
60
5、AWT中的各种组件 //Checkbox add( new Chebox(“one”, null, true) );
add( new Chebox(“two”, null, false) ); add( new Chebox(“three”, null, false) ); //CheckboxGroup CheckboxGroup cbg = new CheckboxGroup(); add( new Chebox(“one”, cbg, true) ); add( new Chebox(“two”, cbg, false) ); add( new Chebox(“three”, cbg, false) ); //Choice Choice ch = new Choice(); ch.add( “Green” ); ch.add( “Red” ); ch.add( “Blue” );
61
5、AWT中的各种组件 标签(Label) 单行文本区(TextField)——TextComponent
静态文字,多用于指示信息,无事件。 单行文本区(TextField)——TextComponent 只能显示一行信息,当按回车键后,会产生ActionEvent事件,可以用ActionListener来监听。 文本输入区(TextArea) ——TextComponent 可以显示多行信息,并且有滚动条支持。按回车键后并不产生事件,如果要判断是否完成输入,需要用其他方法,如用一个结束按钮。 列表(List) 列表提供了很多文本选项,可以同时看到多项,也有滚动条的支持,并且可以单选或多选。当用户单选或多选时,会产生ItemEvent事件。
62
// TextField TextField tf1, tf2, tf3, tf4; tf1 = new TextField(); // a blank text field tf2 = new TextField("", 20); // blank field of 20 columns tf3 = new TextField("Hello!"); // predefined text displayed tf4 = new TextField("Hello", 30); // predefined text in 30 columns //TextArea add( new TextArea("Hello", 5, 40); ); //List List lst = new List(4, false); lst.add("Mercury"); lst.add("Venus"); lst.add("Earth"); lst.add("JavaSoft"); lst.add("Mars"); lst.add("Neptune"); add(lst);
63
5、AWT中的各种组件 滚动条(Scrollbar) 画布(Canvas) CanvasTest.java
滚动条一般不单独使用,它通常与另一个组件联合使用,用以指示另一个组件的变化情况。一般情况下,它可以用ScrollPane代替。 画布(Canvas) 画布类在使用时必须被继承,它本身并不做任何事情,它只是在屏幕上生成了一个矩形空白区域,使应用程序能够在上面任意作画,如写文字、画各种图形、接收键盘或鼠标输入等。如果想在画布上完成图画功能,必须重写其paint()方法。 画布监听各种鼠标、键盘事件,只需实现KeyListener、MouseMotionListener和MouseListener接口即可。 当在画布中输入字符时,必须先调用requestFoucus()方法为画布获得输入焦点,一般在mouseClicked()方法中调用该方法。 CanvasTest.java
64
5、AWT中的各种组件 菜单 菜单与其他组件不同,无法直接添加到容器的某一位置,也无法用布局管理器对其加以控制,它由以下概念支撑:
菜单条(MenuBar) 只能添加到Frame中(用setMenuBar()),作为摆放菜单的容器。 菜单(Menu) 菜单项容器,负责显示并控制其中的菜单项。它支持菜单嵌套。 菜单项(MenuItem) 真正的动作,可以用ActionListener监听其事件(ActionEvent)。 复选框菜单项(CheckboxMenuItem) 真正的动作, 可以用ItemListener监听其事件(ItemEvent)。 弹出式菜单(PopupMenu) 与菜单(Menu)相似,也是菜单项容器,通过其show()方法来显示菜单项。
65
5、AWT中的各种组件 Frame MenuBar … Menu ChKMenuItem MenuItem MenuBar mb;
Menu m; MenuItem mi1, mi2; CheckboxMenuItem mi3; //Build the menu bar. mb = new MenuBar(); setMenuBar(mb); //Frame的方法 //Build first menu in the menu bar. m = new Menu("Menu 1", true); mb.add(m); mi1 = new MenuItem("Menu Item 1"); m.add(mi1); mi2 = new MenuItem("Menu Item 2"); m.add(mi2); mi3 = new CheckboxMenuItem("Menu Item 3"); m.add(mi3);
66
面板可以处理事件,但象画布一样,一定要先获得输入焦点。
5、AWT中的各种组件 框架(Frame) Frame是一个顶级窗口,通常是应用程序的骨架。Frame中的退出按钮被点击后,将产生一个WindowEvent事件,表示关闭Frame,可以在Frame中实现WindowListener接口以监听WindowEvent事件。Frame中无法直接监听键盘事件,但可以往Frame中添加画布、面板凳组件,让它们来负责监听键盘事件。 面板(Panel) 面板可以处理事件,但象画布一样,一定要先获得输入焦点。 对话框(Dialog) 对话框与Frame相类似,一般用于接收用户的输入数据,实现与用户的交互。它与一般窗口的区别在于它依赖其他的窗口。对话框分有模式和无模式两种,前者只让应用程序响应对话框内部事件,后者则可以响应对话框以外的事件,可以通过其构造方法来设置对话框是否有模式: Dialog( Parent, Title, isModal ) //父窗口,标题,是否有模式
67
5、AWT中的各种组件 文件对话框(FileDialog) 滚动窗口(ScrollPane) MyScrollPane.java
表示文件选择的对话框,它是有模式对话框。可以用其getFile()方法来获得要打开或要存储的文件名。 滚动窗口(ScrollPane) 滚动窗口也是容器的一种,象Panel一样,无法单单独使用。使用滚动窗口可以查看大面积的区域,因为它有滚动条。滚动窗口内只能放一个组件,因此也无须布局管理器。通常是在滚动窗口中放一个面板,然后在面板中添加各种组件。滚动窗口中的事件一般由其中的组件来管理。 MyScrollPane.java
68
5、AWT中的各种组件 ——继承Dialog
DialogWindow.java
69
5、AWT中的各种组件 ——继承Component
构造方法: 如果组件要响应事件(如鼠标按键),构造方法中必须调用enableEvents()方法; 更改组件状态的方法: 比如setText()方法等,在这些方法中,如果状态的变化引起了组件外观的变化,则需要调用repaint()方法,如果组件的尺寸发生了变化,则在调用repaint()方法前还需要调用invalidate()方法;
70
5、AWT中的各种组件 ——继承Component 组件的绘制方法:
paint(),还包括组件最佳尺寸getPreferredSize()和最小尺寸getMinimumSize()方法等。 组件的事件监听器注册方法和取消注册方法: addActionListener()和removeActionListener(),在这两个方法中要调用AWTEventMulticaster 类中的方法来实现; contains()方法: 如果组件只响应一定区域中发生的事件; 组件状态改变及事件产生方法: processXXXX(),如processMouseEvent() RoundButtonTest.java
71
6、组件的应用实例 菜单 画布 单行文本输入区 按钮 复选框 下拉式菜单 列表 文本输入区 …… GUIWindow.java
72
6、组件的应用实例 各种AWT组件的详细使用方法、相关的事件处理方法以及其他AWT相关类的使用方法,请大家课后参照课程网站“讲义”中提供的教程(tutorial)和类说明文档(j2sdk-1_3_1-doc)进一步学习。
73
变化外观 UIManager SwingUtilities LookAndFeelInfo
getInstalledLookAndFeels() setLookAndFeel(String name) SwingUtilities updateComponentTreeUI(Componect c) LookAndFeelDemo.java
74
多文档窗口 JDesktopPane JInternalFrame 管理JInternalFrame 子窗口容器
DesktopTest.java
75
1、所有小应用程序的根源 2、小应用程序的执行 3、图形操作 4、载入现有图像文件 5、动画效果 6、播放声音 7、小应用程序的通信
下一讲内容 ——Java Applet 1、所有小应用程序的根源 2、小应用程序的执行 3、图形操作 4、载入现有图像文件 5、动画效果 6、播放声音 7、小应用程序的通信
Similar presentations