第八章 图形用户界面
学习目标:
1.掌握 图形用户界面编程的步骤。
2.掌握 常用布局管理类的使用。
3.掌握 容器的嵌套。
4.掌握 常用组件的使用。
5.理解掌握 事件处理的要素和方式 ( Java中的事件处理机制 )。
一、图形用户界面概述
1、定义
图形用户界面:是程序与用户交互的方式,利用它系统可以接受用户的输入并向用户输出程序运行的结果,能够给用户带来“所见即所得”的效果。
2、类包
- java.awt包:提供了大量进行GUI设计所使用的类和接口,是进行GUI程序设计的基础
- javax.swing包:由100%纯Java实现的,没有本地代码,不依赖操作系统的支持,因而也称为轻量级组件,它的出现使得Java的图形用户界面上了一个台阶。
java.awt包创建的组件都属于重量级组件,依赖于底层操作系统的支持,其显示结果可能因操作系统的不同而不同,所以本文章主要讨论javax.swing包创建的组件。
3、创建图形用户界面主要步骤:
- 创建容器
- 布局管理
- 添加组件
- 事件处理
二、如何创建常用的容器——JFrame类
1、容器
容器Container是一个类,它允许组件被放置在其中。
Container类的继承关系如图:
容器本身也是组件,但主要功能是放置组件和其它的子容器。
继承关系如图:
如何构造JFrame类对象呢?
方法名 | 方法功能 |
---|---|
JFrame() | 构造一个JFrame的一个实例(初始时不可见)。 |
JFrame(String title) | 构造一个初始不可见的、具有指定标题的JFrame对象。 |
方法名 | 方法功能 |
---|---|
boolean isResizable() | frame是否可以调整大小的变量,可用于判断 |
remove(MenuComponent m) | 从frame移除指定的菜单栏 |
setIconImage(Image image) | 设置frame最小化时显示的图标 |
setJMenuBar(MenuBar mb) | 将frame的菜单栏设置为指定的菜单栏 |
setResizable(boolean resizable) | 设置frame是否可以由用户调整窗口大小 |
setTitle(String title) | 设置frame的标题 |
setTitle(String title) | 设置frame的标题 |
setSize(int width,int height) | 设置frame的窗口大小 |
setLocation(int x,int y) | 设置frame的位置,x,y为程序左上角位置的坐标 |
setDefaultColseOperation(int operation) | 可传递四个值:DO_NOTHING_ON_CLOSE:关闭时不做任何事HIDE_ON_CLOSE:关闭时隐藏窗口DISPOSE_ON_CLOSE:关闭窗口及其窗口所占资源EXIT_ON_CLOSE:结束窗口的整个应用程序,退出JVM |
举例:定制窗口
补充:
如何使窗口的宽和高为整个屏幕的1/3?
Toolkit 和 Dimension
Toolkit是抽象类,提供了获取和设置本机系统设备参数和属性的方法。Dimension类,与Toolkit配合使用,可以获得屏幕大小。
eg:
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JButton;
import javax.swing.JFrame;
public class JFrameDemo extends JFrame{
public JFrameDemo() {
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension d = tk.getScreenSize();
//窗口显示在整个屏幕的中央位置
this.setLocation((d.width-d.width/3)/2, (d.height-d.height/3)/2);
this.setSize(d.width/3,d.height/3 );
//设置窗口标题
this.setTitle("Hello Swing");
//设置窗口图标
this.setIconImage(tk.getImage("images/bug1.png"));
//设置窗口尺寸不可调整
this.setResizable(false); //窗口尺寸不可调整
//设置按钮
this.add(new JButton("按钮"));
this.setVisible(true); //窗口可见性
}
public static void main(String[] args) {
new JFrameDemo();
}
}
运行结果:
三、常用的几种布局
当添加组件时,组件的大小、位置等都有一个称为布局管理器的东西控制着。
1、布局管理
Java为了实现跨平台的特性并获得动态的布局效果,将容器内的所有组件安排给一个“布局管理器”负责管理,如排列顺序、组件大小、位置等。
不同的布局管理器使用不同算法和策略,容器可以通过setLayout方法选择不同的布局管理器来决定布局。
Java提供了FlowLayout(流式布局) 、BorderLayout(框架布局/边界布局) 、CardLayout(卡片布局) 、GridLayout (网格布局)、BoxLayout(盒式布局) 、GridBagLayout 等多种布局管理类,以满足不同应用的需求,这些布局管理类包含在java.awt或javax.swing包中。
2、流式布局——FlowLayout
FlowLayout 是 JPanel类 缺省的布局管理器。其组件的放置规律是从上到下、从左到右进行放置。
其构造方法如图:
方法名 | 方法功能 |
---|---|
FlowLayout(int align,int hgap,int vgap); | align:组件的对齐方式;hgap:组件之间的横向间隔;vgap:组件之间的纵向间隔,单位是像素 |
FlowLayout(int align); | 默认水平和垂直间隙是5个像素 |
FlowLayout( ); | 缺省的对齐方式,横向间隔和纵向间隔都是缺省值5个像素 |
3、边界布局——BorderLayout
BorderLayout是JFrame缺省的布局管理器,如图所示它把容器分成5个区域:North,South, East, West 和 Center,每个区域只能放置一个组件。
如图:
其构造方法如图:
方法名 | 方法功能 |
---|---|
BorderLayout(int hgap ,int vgap); | 构造一个具有指定组件间距的边界布局 |
BorderLayout( ); | 构造一个组件之间没有间距的边界布局 |
4、容器嵌套
在复杂的图形用户界面设计中,为了使布局更加易于管理,具有简洁的整体风格,一个包含了多个组件的容器本身也可以作为一个组件加到另一个容器中去,容器中在添加容器,这样就形成了容器的嵌套。
实现容器的嵌套,需要借助于 JPanel 作为中间的容器。
JPanel类的继承关系如图所示:
JPanel常用构造方法:
方法名 | 方法功能 |
---|---|
JPanel(LayoutManager layout) | 创建具有指定布局管理器的 JPanel容器 |
JPanel() | 使用默认的布局管理器 FlowLayout创建 JPanel容器 |
5、卡片布局——CardLayout
实现多个组件共享同一块空间
CardLayout布局将容器中的每个组件看作一张卡片,一次只能看到一张卡片。
主要构造方法如图:
方法名 | 方法功能 |
---|---|
CardLayout( ) | 创建一个间距大小为0的卡片布局 |
CardLayout( int hgap, int vgap) | 创建一个指定水平间距和垂直间距的卡片布局 |
实例方法如图:
方法名 | 方法功能 |
---|---|
void first(Container parent) | 移到指定容器的第一张卡片 |
void next(Container parent) | 移到指定容器的下一张卡片 |
void previous(Container parent) | 移到指定容器的前一张卡片 |
void last(Container parent) | 移到指定容器的最后一张卡片 |
void show(Container parent, String name) | 显示指定卡片 |
6、网格布局——GridLayout
GridLayout布局以矩形网格形式对容器的组件进行布置。容器被分成大小相等的矩形,一个矩形中放置一个组件。
构造放法如图:
方法名 | 方法功能 |
---|---|
GridLayout() | 以默认的单行、每列布局一个组件的方式构造网格布局 |
GridLayout(int rows,int cols) | 以指定的行和列构造网格布局 |
GridLayout(int rows,int cols,int hgap, int vgap) | 以指定的行、列、水平间距和垂直间距构造网格布局 |
四、事件处理
Java事件处理四要素:
- 事件源:究竟是谁引发了事件的发生。在面向对象编程语言中,事件源指的是引发事件发生的各个组件。
- 事件:即引发了什么类型的事件发生。在Java中不同类型的事件会对应相应的事件类。
- 事件处理者:究竟谁有能力对事件进行处理。
- 注册:建立事件源和事件处理者的关联。
eg:
事件处理要素 | 珠宝店被盗 | 用户单击按钮 |
---|---|---|
事件源 | 珠宝店 | 按钮对象 |
事件 | 被盗 | 用户单击触发ActionEvent类事件 |
事件处理者 | 保安 | 实现ActionListener接口的类对象 |
注册 | 珠宝店雇佣保安 | 按钮对象 .addActionListener(事件处理者); |
不同事件类型Java中是使用不同的类来描述的,大多数事件类包含在java.awt.event包里,所有事件类的父类都是 AWTEvent 类。
常用事件类型:
事件类型 | 触发事件的动作 |
---|---|
ActionEvent | 当用户单击按钮、选择菜单项或选择一个列表项时产生 ActionEvent 事件 |
ItemEvent | 当用户在组合框选择一项时产生ItemEvent 事件 |
TextEvent | 当文本域或文本框中的内容发生变化时产生 TextEvent事件 |
FocusEvent | 组件得到焦点或失去焦点时发生 |
WindowEvent | 窗口被激活、图标化、还原或关闭时发生 |
KeyEvent | 按下或释放一个键时发生 |
MouseEvent | 按下、释放鼠标按钮,移动或拖动鼠标时发生 |
对应的监听接口:
在进行事件处理时,如果通过实现接口的话,必须要实现该接口所要求实现的所有方法,即使有些方法我们不需要实现,也必须实现。
因此,Java设计者设计了一种特殊的API类,称之为适配器(Adapter)。
适配器实现了对应的接口,只不过是空实现,这样一来,如果通过继承适配器的方式,我们就可以根据需要重写我们关心的方法,大大的简化事件处理编程。
各个监听接口对应的适配器如图: