一、相关概述
GUI编程是指通过图形化的方式来实现计算机程序的编写,它可以让用户通过鼠标、键盘等设备来操作计算机,而不是通过命令行来输入指令。在Java中,GUI编程主要使用的是Swing和AWT两种技术
二、AWT
2.1介绍
AWT是Java提供的用来建立和设置Java的图形用户界面的基本工具,它提供了一套与本地图形界面进行交互的接口12。AWT的图形函数与操作系统提供的图形函数有着一一对应的关系,也就是说,当使用AWT时,Java程序会调用操作系统的图形函数来绘制界面
2.2组件和容器
容器是Component的子类,一个容器可以容纳多个组件,并使他们成为一个整体。容器可以简化图形化界面的设计,以整体结构来布置界面,所有的组件都可以通过add()方法加入容器中。
组件
- 窗口
- 弹窗
- 面板
- 文本框
- 列表框
- 按钮
- 图片
- 监听事件
- 鼠标
- 键盘事件
- 破解工具
2.2.1窗口(Frame)
package com.tanchise;
import java.awt.*;
public class FirstFrame extends Frame{
public static void main(String[] args) {
// TODO Auto-generated method stub
FirstFrame fr = new FirstFrame("Hello world!"); //构造方法
fr.setSize(240,240); //设置Frame的大小
fr.setBackground(Color.blue); //设置Frame的背景色
fr.setLocation(200,200);//弹出初始位置
fr.setVisible(true); //设置Frame为可见,默认不可见
fr.setResizable(false);//设置Frame大小固定
}
public FirstFrame(String str){
super(str);
}
}
效果图
注:awt在实际运行过程中,是调用所在平台的图形系统,底层实现依赖操作系统,为此在Windows平台下运行,则显示Windows风格。
package com.tanchise;
import java.awt.*;
public class FirstFrame2 {
public static void main(String[] args) {
MyFrame myFrame1 = new MyFrame(100,100,200,200,Color.yellow);
MyFrame myFrame2 = new MyFrame(300,200,200,200,Color.blue);
}
}
class MyFrame extends Frame{
static int count = 0;
public MyFrame(int x,int y,int w,int h,Color color) {
super("Myframe+"+(++count));
setBackground(color);
setBounds(x,y,w,h);
setVisible(true);
}
}
2.2.2、面板(Panel)
Panel是一种透明的容器,既没有标题,也没有边框。它不能作为最外层的容器单独存在,首先必须先作为一个组件放置在其他容器中,然后在把它当做容器。
package com.tanchise;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class panel {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame fr = new Frame("Hello");
fr.setSize(240,240);
fr.setBackground(Color.green);
fr.setLayout(null); //取消默认的布局BorderLayout
Panel pan = new Panel(); //创建面板
pan.setSize(100,100);
pan.setBackground(Color.yellow);
fr.add(pan);
fr.setVisible(true);
//
fr.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
效果图
2.3、布局管理器(LayoutManager)
为了实现跨平台并获得动态的布局效果,java将容器内的所有组件安排给一个“布局管理器”负责管理,如:排列顺序、组件大小、位置、当窗口移动或调整大小后组件变化等功能授权给对应的容器布局管理器来管理。
- 流式布局
- 东、西、南、北、中布局
- 表格布局
2.3.1、FlowLayout——流式布局管理器
FlowLayout 会将组件按照从上到下、从左到右的放置规律逐行进行定位。与其他布局管理器不同的是,FlowLayout 布局管理器不限制它所管理组件的大小,而是允许它们有自己的最佳大小。FlowLayout 布局管理器的构造方法如下:
- FlowLayout ():创建一个布局管理器,使用默认的居中对齐方式和默认 5 像素的水平和垂直间隔。
- FlowLayout (int align):创建一个布局管理器,使用默认 5 像素的水平和垂直间隔。
package com.tanchise;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class FlowLayoutDemo {
public static void main(String[] args) {
Frame frame = new Frame("FlowLayout"); //Frame默认的布局管理器为BorderLayout
frame.setBounds(100, 100, 400, 300);
frame.setLayout(new FlowLayout(FlowLayout.CENTER)); //设置布局管理器为FlowLayout
Button but1 = new Button("button1");
Button but2 = new Button("button2");
Button but3 = new Button("button3");
Button but4 = new Button("button4");
Button but5 = new Button("button5");
but1.setBackground(Color.blue);
but2.setBackground(Color.yellow);
but3.setBackground(Color.red);
but4.setBackground(Color.green);
but5.setBackground(Color.pink);
frame.add(but1);
frame.add(but2);
frame.add(but3);
frame.add(but4);
frame.add(but5);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
效果图
FlowLayout的对齐方式默认为居中对齐,但是我们也可以自己指定对齐方式及横纵向间隔。
2.3.2、BorderLayout——边框布局管理器
边框布局管理器是Java Swing中的一种布局管理器,它将容器分为五个区域:东、南、西、北和中。每个区域只能包含一个组件,如果没有指定组件的位置,则默认将其放置在中央区域。
package com.tanchise;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class BorderLayoutDemo {
public static void main(String[] args) {
Frame frame = new Frame("BorderLayt");
frame.setBounds(100, 100, 400, 300);
//frame.setLayout(new BorderLayout()); //设置 frame的布局为BorderLayout,默认也是此布局
Button btn1 = new Button("button1");
Button btn2 = new Button("button2");
Button btn3 = new Button("button3");
Button btn4 = new Button("button4");
Button btn5 = new Button("button5");
btn1.setBackground(Color.blue);
btn2.setBackground(Color.yellow);
btn3.setBackground(Color.pink);
btn4.setBackground(Color.green);
btn5.setBackground(Color.red);
frame.add(btn1,BorderLayout.EAST);
frame.add(btn2,BorderLayout.NORTH);
frame.add(btn3,BorderLayout.SOUTH);
frame.add(btn4,BorderLayout.WEST);
frame.add(btn5);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
效果图
2.3.3、GridLayout——网格布局管理器
网格布局管理器是Java Swing中的一种布局管理器,它将容器分成行数和列数相等的网格,每个网格放置一个组件,按照从左往右,从上往下的顺序依次添加
package com.tanchise;
import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class GridLayoutDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame frame = new Frame("GridLayout");
frame.setBounds(400, 400, 500, 400);
GridLayout gl = new GridLayout(3,2,5,5); //设置表格为3行两列排列,表格横向间距为5个像素,纵向间距为5个像素
frame.setLayout(gl);
Button but1 = new Button("button1");
Button but2 = new Button("button2");
Button but3 = new Button("button3");
Button but4 = new Button("button4");
Button but5 = new Button("button5");
but1.setBackground(Color.blue);
but2.setBackground(Color.yellow);
but3.setBackground(Color.red);
but4.setBackground(Color.green);
but5.setBackground(Color.pink);
frame.add(but1);
frame.add(but2);
frame.add(but3);
frame.add(but4);
frame.add(but5);
// frame.pack();//自动布局
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
效果图
2.3.4GridBagLayout——网格包布局管理器
GridBagLayout是Java Swing中的一个布局管理器,它可以在一个网格中放置组件,每个组件占用一个或多个网格单元格。GridBagLayout是最灵活和复杂的布局管理器之一,它可以让指定的组件跨越多行或多列。不是所有的行都必须具有相同的高度
package com.tanchise;
import java.awt.Button;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class GridBagLayoutDemo {
// 创建一个 Frame 对象,名为 "GridBagLayout Test"
private Frame f = new Frame("GridBagLayout Test");
// 创建一个 GridBagLayout 布局管理器对象
private GridBagLayout gbl = new GridBagLayout();
// 创建一个 GridBagConstraints 对象
private GridBagConstraints gbc = new GridBagConstraints();
// 创建一个 Button 类型的数组对象,长度为 10
private Button[] btns = new Button[10];
// 添加按钮的方法,接收一个 Button 类型的参数 btn
private void addButton(Button btn) {
// 使用 gbl 对象设置按钮的约束条件
gbl.setConstraints(btn, gbc);
// 将按钮添加到 Frame 对象中
f.add(btn);
}
// 初始化方法
public void init() {
// 循环创建 10 个按钮,将它们添加到数组中
for (int i = 0; i < 10; i++) {
btns[i] = new Button("button" + i);
}
// 设定 Frame 的布局模式为 GridBagLayout
f.setLayout(gbl);
// 设置组件填充方式为 BOTH,即组件完全填满其显示区域
gbc.fill = GridBagConstraints.BOTH;
// 设置组件水平所占用的格子数为 1,如果为 0,说明该组件是该行的最后一个,为 1 则只占一格
gbc.weighty = 1;
// 第 1 行的 4 个按钮
// 设置组件水平的拉伸幅度为 1,即随着窗口增大进行拉伸,0 到 1 之间
gbc.weightx = 1;
// 将按钮 0、1、2 添加到 Frame 中
addButton(btns[0]);
addButton(btns[1]);
addButton(btns[2]);
// 该组件是该行的最后一个,第 4 个添加后就要换行了
gbc.gridwidth = GridBagConstraints.REMAINDER;
// 将按钮 3 添加到 Frame 中
addButton(btns[3]);
// 第 2 行 1 个按钮,仍然保持 REMAINDER 换行状态
// 将按钮 4 添加到 Frame 中
addButton(btns[4]);
// 第 3 行
// 按钮分别横跨 2 格
gbc.gridwidth = 2;
// 设置组件水平的拉伸幅度为 1
gbc.weightx = 1;
// 将按钮 5 添加到 Frame 中
addButton(btns[5]);
// 该组件是该行的最后一个
gbc.gridwidth = GridBagConstraints.REMAINDER;
// 将按钮 6 添加到 Frame 中
addButton(btns[6]);
// 按钮 7 纵跨 2 个格子,8、9 一上一下
// 按钮 7 纵跨 2 格
gbc.gridheight = 2;
gbc.gridwidth = 1;
gbc.weightx = 1;
addButton(btns[7]);
// 该组件是该行的最后一个
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = 1;
gbc.weightx = 1;
addButton(btns[8]);
addButton(btns[9]);
// 将 Frame 自适应大小,并显示
f.pack();
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public static void main(String[] args) {
new GridBagLayoutDemo().init();
}
}
2.3.5CardLayout——卡片布局管理器
卡片布局管理器(CardLayout)是Java Swing中的一种布局管理器,它能够帮助用户实现多个成员共享同一个显示空间,并且一次只显示一个容器组件的内容。CardLayout布局管理器将容器分为很多层,每层的显示空间占据整个容器的大小,但是每层只允许放置一个组件。
package com.tanchise;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.CardLayout;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class aaa {
Frame f = new Frame("测试窗口");
String[] names = { "one", "two", "three", "four", "five" };
Panel p1 = new Panel(); //显示的面板
public void init() {
final CardLayout c = new CardLayout(); //卡片局部
p1.setLayout(c); //面板布局使用卡片布局
for (int i = 0; i < names.length; i++) {
p1.add(names[i], new Button(names[i])); //设置面板的名字和组件
}
Panel p = new Panel(); //创建一个放按钮的面板
// 控制显示上一张的按钮
Button previous = new Button("pre");
//为按钮添加监听
previous.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
c.previous(p1);
}
});
// 控制显示下一张的按钮
Button next = new Button("next");
next.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
c.next(p1);
}
});
// 控制显示第一张的按钮
Button first = new Button("first");
first.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
c.first(p1);
}
});
// 控制显示最后一张的按钮
Button last = new Button("last");
last.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
c.last(p1);
}
});
// 控制根据Card显示的按钮
Button third = new Button("Third");
third.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
c.show(p1, "three");
}
});
p.add(previous);
p.add(next);
p.add(first);
p.add(last);
p.add(third);
f.add(p1);
f.add(p, BorderLayout.SOUTH);
f.pack(); //紧凑排列
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public static void main(String[] args) {
new aaa().init();
}
}
2.4、组件(Component)
awt组件库中还有很多比较常用的组件,如:按钮(Button)、复选框(Checkbox)、复选框组(CheckboxGroup)、下拉菜单(Choice)、单行文本输入框(TextField)、多行文本输入框(TextArea)、列表(List)、对话框(Dialog)、文件对话框(Filedialog)、菜单(Menu)、MenuBar、MenuItem、Canvas等;
2.4.1、基本组件
package com.tanchise;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Choice;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
public class ComponentTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame frame = new Frame("基本组件测试");
frame.setBounds(100, 100, 600, 300);
GridLayout gl = new GridLayout(4,2,5,5); //设置表格为3行两列排列,表格横向间距为5个像素,纵向间距为5个像素
frame.setLayout(gl);
//按钮组件
Button but1 = new Button("bottom");
Panel pn0 = new Panel();
pn0.setLayout(new FlowLayout());
pn0.add(but1);
frame.add(pn0);
//复选框组件
Panel pn1 = new Panel();
pn1.setLayout(new FlowLayout());
pn1.add(new Checkbox("one",null,true));
pn1.add(new Checkbox("two"));
pn1.add(new Checkbox("three"));
frame.add(pn1);
//复选框组(单选)
Panel pn2 = new Panel();
CheckboxGroup cg = new CheckboxGroup();
pn2.setLayout(new FlowLayout());
pn2.add(new Checkbox("one",cg,true));
pn2.add(new Checkbox("two",cg,false));
pn2.add(new Checkbox("three",cg,false));
frame.add(pn2);
//下拉菜单
Choice cC = new Choice();
cC.add("red");
cC.add("green");
cC.add("yellow");
frame.add(cC);
//单行文本框
Panel pn3 = new Panel();
pn3.setLayout(new FlowLayout());
TextField tf = new TextField("",30); //30列长度
pn3.add(tf);
frame.add(pn3);
//多行文本框
TextArea ta = new TextArea();
frame.add(ta);
//列表
List ls = new List();
ls.add("a");
ls.add("b");
ls.add("c");
ls.add("d");
ls.add("e");
ls.add("f");
ls.add("g");
frame.add(ls);
frame.setVisible(true);
}
}
2.4.2Menu组件
Java中的Menu组件是一个下拉菜单,它可以从菜单栏中部署。菜单可以选择是撕开式菜单。撕开式菜单可以从其父菜单栏或菜单中打开并拖动。鼠标按钮释放后,它仍然保留在屏幕上。
package com.tanchise;
import java.awt.Frame;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
public class MenuDemo {
private Frame f;
public MenuDemo(){
f = new Frame("测试菜单");
f.setBounds(100, 100, 200, 200);
//Menu无法直接添加到容器中,只能直接添加到菜单容器中
MenuBar mb = new MenuBar(); //创建菜单容器
f.setMenuBar(mb);
//添加菜单
Menu m1 = new Menu("File");
Menu m2 = new Menu("Edit");
Menu m3 = new Menu("Help");
mb.add(m1);
mb.add(m2);
mb.add(m3);
//添加菜单项
MenuItem mi1 = new MenuItem("Save");
MenuItem mi2 = new MenuItem("Load");
MenuItem mi3 = new MenuItem("Quit");
m1.add(mi1);
m1.add(mi2);
m1.addSeparator(); //添加分隔线
m1.add(mi3);
f.setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MenuDemo md = new MenuDemo();
}
}
三、事件监听
在Java GUI编程中,事件监听器是一种机制,用于处理用户与GUI组件交互时发生的事件。Java中,事件处理的基本思路是:一个源(事件源)产生一个事件,并把它送到监听器那里,监听器只是简单的对待,直到它收到一个事件,一旦事件被接收,监听器将处理这些事件。一个事件源必须注册监听器以便监听器可以接收关于一个特定事件的通知
与AWT有关的所有事件类都由AWTEvent类派生,它是EventObject类的子类。这些AWT事件分为两大类:低级事件和高级事件。低级事件是指基于组件和容器的事件,当一个组件上发生事件,如鼠标进入、点击、拖放或组件的窗口开关等都是低级事件。高级事件是语义事件,它不可以和特点的动作相关联,而依赖于触发此类事件的类,如选中项目列表中的某一项就会触发ActionEvent事件。
低级事件:
1)ComponentEvent 构件事件,构件尺寸的变化以及移动·
2)ContainerEvent 容器事件,构件增加,移动
3)WindowEvent 窗口事件,关闭窗口,窗口闭合,图标化
4)FocusEvent 焦点事件,焦点的获得与丢失
5)KeyEvent 键盘事件,键按下,释放
6)MouseEvent 鼠标事件,鼠标点击,移动
高级事件(语义事件):
1)ActionEvent 动作事件,按键按下,TextField中按下Enter键
2)AdjustmentEvent 调节事件,在滚动条上移动滑块以调节数值
3)ItemEvent 项目事件,选择项目,不选择“项目改变”
· 4)TextEvent 文本事件,文本对象改变
3.1、事件监听器概述
每类事件都有对应的事件监听器,AWT一共10类事件,11个接口。
3.2Button按钮监听器
package com.tanchise;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class buttonActionEvent {
public static void main(String[] args) {
//按下按钮,触发一些事件
Frame frame = new Frame();
frame.setBounds(100, 100, 400, 400);
Button button = new Button("Button");
button.setBackground(Color.blue);
button.setSize(1,1);
//因为,addActionListener()需要ActionListener,所以需要构造一个ActionListener
MyActionListener myActionListener = new MyActionListener();
button.addActionListener(myActionListener);
frame.add(button);
// frame.pack();
windowClose(frame);//关闭窗口
frame.setVisible(true);
}
//关闭窗体事件
private static void windowClose(Frame frame){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class MyActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("aab");
}
}
多个按钮,共享一个事件
package com.tanchise;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestActionTwo {
public static void main(String[] args) {
//两个按钮,实现同一个监听
//开始 停止
Frame frame = new Frame("开始-停止");
frame.setBounds(100, 100, 400, 400);
Button button1 = new Button("start");
button1.setBackground(Color.blue);
button1.setSize(10, 10);
Button button2 = new Button("stop");
//可以显示的定义触发会返回的命令,如果不显示定义,会走默认的值
//可以多个按钮只写一个监听
button2.setActionCommand("button2-stop");
MyMonitor myMonitor = new MyMonitor();
button1.addActionListener(myMonitor);
button2.addActionListener(myMonitor);
frame.add(button1, BorderLayout.NORTH);
frame.add(button2, BorderLayout.WEST);
// frame.pack();
windowClose(frame);//关闭窗口
frame.setVisible(true);
}
private static void windowClose(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class MyMonitor implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
//e.getActionCommand()获取按钮的信息
System.out.println("按钮被点击了:msg"+e.getActionCommand());
}
}
3.3输入框TextField监听
package tanchishe;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TextField1 {
public static void main(String[] args) {
new myframe();
}
}
class myframe extends Frame {
public myframe(){
TextField textField = new TextField();
add(textField);
//监听这个文本框输入的文字
MyActionListener2 myActionListener2 = new MyActionListener2();
//按下enter,就会触发这个输入框的事件
textField.addActionListener(myActionListener2);
//设置替换编码
textField.setEchoChar('*');
setVisible(true);
pack();
}
}
class MyActionListener2 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
TextField field = (TextField)e.getSource();//获得一些资源,返回一个对象
System.out.println(field.getText());//获得输入框的文本
field.setText("");
}
}
简易计算机
package tanchishe;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TextCale {
public static void main(String[] args) {
new Calculator().loadFrame();
}
}
//计算机类
class Calculator extends Frame{
//属性
TextField num1,num2,num3;
//方法
public void loadFrame(){
//3个文本框
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(20);
//1个按钮
Button button = new Button("=");
button.addActionListener(new MyCalculatorListener(this));
//1个标签
Label label = new Label("+");
//布局
setLayout(new FlowLayout());
add(num1);
add(label);
add(num2);
add(button);
add(num3);
pack();
setVisible(true);
}
}
//监听器类
class MyCalculatorListener implements ActionListener{
//获取计算机这个对象,在一个类中组合另一个类
Calculator calculator = null;
public MyCalculatorListener(Calculator calculator){
this.calculator=calculator;
}
@Override
public void actionPerformed(ActionEvent e) {
//1、获得加数和被加数
//2、将这个值+法运算后,放到第三个框
//3、清楚前两个框
int n1 = Integer.parseInt(calculator.num1.getText());
int n2 = Integer.parseInt(calculator.num2.getText());
calculator.num3.setText(""+(n1+n2));
calculator.num1.setText("");
calculator.num2.setText("");
}
}