——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
黑马程序员–Java之GUI(10)
一、概述
GUI全称是Graphical User Interface,即图形用户界面。就是应用程序提供给用户操作的图形界面,包括窗口、菜单、按钮、工具栏和其他各种图形界面元素。Java中针对GUI设计提供了丰富的类库,这些类分别位于java.awt和javax.swing包中,简称为AWT和Swing。
在AWT中组件分为两大类,这两类的父类分别是Component和MenuComponent。MenuComponent是所有与菜单组件相关组件的父类,Component则是除菜单外其他AWT组件的父类,它表示一个能以图形化方式显示出来,并可与用户交互的对象。
Component类通常被称为组件,根据Component的不同作用,可将其分为基本组件类和容器类。基本组件类如按钮、文本框之类的图形界面元素,而容器类则是通过Component的子类Container实例化的对象。Container类表示容器,是一种特殊的组件,可以用来容纳其他组件。Container容器又分为两种,Window和Panel。
Window类的不依赖其他容器而独立存在容器,有两个子类,Frame类和Dialog类。Frame类用于创建一个具有标题栏的框架窗口,作为程序的主界面,Dialog类用于创建一个对话框,实现与用户的信息交互。
Panel也是一个容器,但是它不能单独存在,只能存在在其他容器(Window或其子类)中,一个Panel对象代表一个长方形的区域,在这个区域中可以容纳其他组件。
二、事件处理
2.1、事件处理机制
- 事件对象(Event):封装了GUI组件上发生的特定事件。
- 事件源(组件):事件发生的场所,通常就是产生事件的组件。
- 监听器(Listener):负责监听事件源上发生的事件,并对各种事件作出相应处理的对象(包括事件处理器)。
- 事件处理器:监听器对象对接收的事件对象进行相应处理的方法。
在程序中,如果想实现事件的监听机制,需要先定义一个类实现事件监听器的接口:
import java.awt.*;
import java.awt.event.*;
//因为import java.awt.*;不能导入子包中的类,所以还需要导入子包
public class addListenerTest{
public static void main(String[] args){
//建立新窗体
Frame f =new Frame("MyFrame");
//设置窗体的宽和高
f.setSize(400,300);
//设置窗体出现的位置
f.setLocation(300,200);
//设置窗体可见
f.setVisible(true);
//为窗体组件添加监听器
MyWindowListener mw = new MyWindowListener();
f.addWindowListener(mw);
}
}
//创建MyWindowListener类实现WindowListener接口
class MyWindowListener implements WindowListener{
//监听器监听事件对象并做出处理
public void windowClosing(windowEvent e){
Window window = e.getWindow();
window.setVisible(false);
//释放窗口
window.dispose();
}
public void windowActivated(WindowEvent e){
}
public void windowClosed(WindowEvent e){
}
public void windowDeactivated(WindowEvent e){
}
public void windowDeiconified(WindowEvent e){
}
public void windowIconified(WindowEvent e){
}
public void windowOpened(WindowEvent e){
}
}
Window类型的窗口需要实现WindowListener,通过addWindowListener()方法为事件注册事件监听对象,当事件源上发生事件时,便会触发事件监听器对象,由事件监听器调用相应的方法来处理相应的事件。
2.2、事件适配器
JDK提供了一些适配器类,它们是监听器接口的默认实现类,这些实现类中实现了接口的所有方法,但方法中没有任何代码。程序可以通过继承适配类来达到实现监听器接口的目的。
import java.awt.*;
import java.awt.event.*;
public class EventAdapter{
public static void main(Stirng[] args)[
//建立新窗体
Frame f = new Frame("MyFrame");
f.setSize(400,300);
f.setLocation(200,300);
f.setVisible(true);
f.addWindowListener(new MyWindowListener());
}
}
//继承WindowAdaper类,并重写windowClosing()方法
class MyWindowListener extends WindowAdapter{
public void windowClosing(WindowEvent e){
Window window =(Window)e.getComponent();
window.dispose();
}
}
几乎所有的监听器接口都有对应的适配器类,通过继承适配器类来实现监听器接口时,需要处理哪种事件,就重写该事件对应的方法。
2.3、匿名内部类实现事件处理
import java.awt.*;
import java.awt.event.*;
pbulic class Test2{
public static void main(String[] args){
Frame f = new Frame("MyFrame");
f.setSize(400,300);
f.setLocation(300,200);
f.setVisible(true);
Button btn = new Button("EXIT");//创建按钮组件对象
f.add(btn);//把按钮对象加载到窗口上
//用内部类的方式为按钮组件注册监听器
btn.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
System.exit(0);
}
};
}
}
调用按钮btn的addMouseListener()方法,并在该方法中以匿名内部类的方式给按钮注册一个鼠标事件监听器。由于只需要监听按钮的点击事件,因此使用了MouseAdapter适合器类,重写了mouseClicked()方法,当按钮被点击时,会把点击事件作为对象传递给事件监听器,做出退出程序的处理。
3、事件分类
在AWT中大致把事件分为窗体事件(WindowEvent)、鼠标事件(MouseEvent)、键盘事件(KeyEvent)、动作事件(ActionEvent)。
4、布局管理器
4.1、FlowLayout
流式布局管理器(FlowLayout)会将组件按照添加顺序从左向右放置。当达到容器的边界时,会自动将组件放到下一行的开始位置。可以设置左对齐、居中对齐(默认)、右对齐。
- FlowLayout()
组件默认居中对齐,水平、垂直间距默认为5个单位
- FlowLayout(int align)
指定组件相对于容器的对齐方式,水平、垂直间距默认为5个单位
- FlowLayout(int align, int hgap)
指定组件的对齐方式和水平、垂直间距
import java.awt.*;
import java.awt.event.*;
public class FlowLayoutTest{
public static void main(String[] args){
final Frame f = new Frame("MyFlowLayout");//创建窗体
f.setSize(200,300);
f.setLocation(300,200);
//设置窗体的布局管理器为FlowLayout,所有组件左对齐,水平间距20,垂直间距30
f.setLayout(new FlowLayout(FlowLayout.LEFT,20,30);
Button btn1 = new Button("第1个按钮");//创建按钮
f.add(btn1);//把按钮添加到窗口中
//添加动作事件监听器,每点击一次“第1个按钮”就向窗体中添加一个按钮
btn1.addActionListener(new ActionListener(){
private int num = 1;//记录按钮个数
public void actionPerformed(ActionEvent e){
f.add(new Button("第" + num + "个按钮");//向窗体中添加按钮
f.setVisible(true);//刷新窗体显示新按钮
}
});
f.setVisible(true);//设置窗体可见
}
}
4.2、BorderLayout
BorderLayout(边界布局管理器)是一种较为复杂的布局方式,它将容器划分为五个区域,分别是东(EAST)、南(SOUTH)、西(WEST)、北(NORTH)、中(CENTER)。其中NORTH和SOUTH区域高度不变长度可调整,EAST和WEST长度不变高度可调整,CENTER会相应进行调整。
import java.awt.*;
public class BorderLayoutTest{
public static void main(Stirng[] args){
final Frame f = new Frame("BorderLayout");
f.setLayout(new BorderLayout());//设置窗体中的布局管理器为BorderLayout
f.setSize(300,400);
f.setLocation(300,200);
f.setVisible(true);
//创建五个按钮,分别用于填充BorderLayout的五个区域
Button btn1 = new Button("东部");
Button btn2 = new Button("南部");
Button btn3 = new Button("西部");
Button btn4 = new Button("北部");
Button btn5 = new Button("中部");
//将创建好的按钮添加到窗体中,并设置按钮所在的区域
f.add(btn1,BorderLayout.EAST);
f.add(btn2,BorderLayout.SOUTH);
f.add(btn3,BorderLayout.WEST);
f.add(btn4,BorderLayout.NORTH);
f.add(btn5,BorderLayout.CENTER);
}
}
4.3、GridLayout
GridLayout(网格布局管理器)使用纵横线将容器分成n行m列大小相等的风格,每个风格中放置一个组件。添加到容器中的组件首先放置在第1行第1列的风格中,然后从左向右依次放置其他组件,行满后继续在下一行中放置组件。与FlowLayout不同的是,GridLayout布局管理器中的组件将会自动占据风格的整个区域。
- GridLayout()
默认只有一行,每个组件占一列
- GridLayout(int rows, int cols)
指定容器的行数和列数
- GridLayout(int rows, int cols,int hgap,int vgap)
指定容器的列数和行数,以及组件之间的水平、垂直间距
4.4、GridBagLayout
GridBagLayout(网格包布局管理器)是最灵活、最复杂的布局管理器。与GridLayout布局管理类似,不同的是,它允许网格中的组件大小各不相同。而且允许一个组件跨越一个或者多个网格。
1. 创建GridBagLayout布局管理器,并使容器采用该布局管理器
GridBagLayout layout = new GridBagLayout();
container.setLayout(layout);
- 创建GridBagConstraints对象(布局约束条件),并设置该对象的相关属性
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 1;
constraints.gridy = 1;
constraints.gridwidth = 1;
constraints.gridheight =1;
- 调用GridBagLayout对象的setConstraints()方法建立GridBagConstraints对象和受控组件之间的关联
layout.setConstraints(component,constraints);
- 向容器中添加组件
container.add(conponent);
GridBagConstraints 对象可以重复使用,只需要改变它的属性即可
4.5、CardLayout
CardLayout(卡片布局管理器)的方法:
- void first(Container paren)
显示parent容器的第一张卡片
- void last(Container paren)
显示parent容器的最后一张卡片
- void previous(Container paren)
显示parent容器的前一张卡片
- void next(Container paren)
显示parent容器的下一张卡片
- void show(Container paren, String name)
显示parent容器中名称为name的组件,如果不存在,则不会发生任何操作
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
//定义CardLayout继承Frame类,实现ActionListener接口
class CardLayout extends Frame implements ActionListener{
Panel cardPanel = new Panel();//定义Panel面板放置卡片
Panel controlpaPanel = new Panel();//定义Panel面板放置按钮
Button nextButton,preButton;
CardLayout cardLayout = new CardLayout();//定义卡片布局对象
public CardLayout(){//定义构造方法,设置卡片布局管理器的属性
setSize(300,200);
setVisible(true);
//为窗口添加关闭事件监听器
this.addWindowListener(new WinodwAdapter(){
public void windowClosing(windowEvent e){
Cardlayout.this.dispose();
}
});
cardPanel.setLayout(cardLayout);//设置cardPanel面板对象为卡片布局
//在cardPanel面板对象中添加三个文本标签
cardPanel.add(new Label("第一个界面",Label.CENTER));
cardPanel.add(new Label("第二个界面",Label.CENTER));
cardPanel.add(new Label("第三个界面",Label.CENTER));
//创建两个按钮对象
nextButton = new Button("下一张卡片");
preButton = new Button("上一张卡片");
//为按钮对象注册监听器
nextButton.addActionListener(this);
preButton.addAciotnlistener(this);
controlpaPanel.add(preButton);
controlpaPanel.add(nextButton);
this.add(cardPanel,BordLayout.CENTER);
this.add(controlpaPanel,BorderLayout.SOUTH);
}
//定义监听事件处理
public void actionPerformed(ActionEvent e){
//如果用户单击nextButton,执行下面语句
if(e.getSource() == nextButton){
//切换cardLayout面板中当前组件之后的一个组件
cardLayout.next(cardPanel);
}
if(e.getSource() == preButton){
//切换cardLayout面板中当前组件之前的一个组件
cardLayout.previous(cardPanel);
}
}
}
public class Test3{
public static void main(String[] args){
CardLayout cardLayout = new CardLayout();
}
}