1、GUI简介
1.1、概述
图形用户界面简称GUI,又称图形用户接口,是指采用图形方式显示的计算机操作用户界面。是一种人与计算机通信的界面显示格式,允许用户使用鼠标等输入设备操纵屏幕上的图标或菜单选项,以选择命令、调用文件、启动程序或执行其他一些日常任务。
我们也可以使用Java来实现GUI编程。而在Java中Gui的核心技术为:Swing AWT;
1.2、组件
- 窗口
- 弹窗
- 面板
- 文本框
- 列表框
- 按钮
- 图片
- 监听事件
- 鼠标事件
- 键盘事件
- 破解工具
2、AWT
2.1、Awt介绍
- 包含了很多类和接口!
- 元素:窗口、按钮、文本框
- java.awt
2.2、组件和容器
- 界面Frame
package org.star.demo;
import java.awt.*;
public class TestFrame {
public static void main(String[] args) {
Frame frame = new Frame("我的第一个Java图像界面窗口");
//设置窗口大小
frame.setSize(300, 400);
//设置背景颜色
frame.setBackground(Color.BLACK);
//或者new Color类,后面的参数对应颜色
//frame.setBackground(new Color(56,56,65));
//弹出的窗口位置
frame.setLocation(100, 100);
//设置大小固定 false表示大小不可变
frame.setResizable(false);
//设置可见性
frame.setVisible(true);
}
}
由于没有设置窗口的关闭,所以点 X 无法关闭,我们可以直接停止Java程序
利用封装我们展示多个窗口:
package org.star.demo;
import java.awt.*;
public class TestFrame2 {
public static void main(String[] args) {
new MyFrame(100, 100, 200, 200, Color.blue);
new MyFrame(300, 100, 200, 200, Color.yellow);
new MyFrame(100, 300, 200, 200, Color.red);
new MyFrame(300, 300, 200, 200, Color.green);
}
}
class MyFrame extends Frame {
static int num = 0;
//我们在构造方法中传入窗口的位置、大小、颜色这几个参数
public MyFrame(int x, int y, int w, int h, Color color) {
//调用父类的构造方法给窗口命名
super("MyFrame" + (++num));
//由于继承了Frame,可以继承Frame类的所以方法
setBounds(x, y, w, h);//此方法可以直接将位置,大小一起设置
setBackground(color);
setVisible(true);
}
}
- Panel
解决关闭事件!
package org.star.demo;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestPanel {
public static void main(String[] args) {
//Panel可以看成时一个空间,但是不能单独存在,必须在窗口中
Frame frame = new Frame();
Panel panel = new Panel();
//设置布局
frame.setLayout(null);
//设置位置颜色
frame.setBounds(100, 100, 300, 400);
frame.setBackground(Color.BLACK);
//设置面板的坐标颜色,相对于窗口的坐标
panel.setBounds(50, 50, 100, 100);
panel.setBackground(Color.red);
//将面板放入窗口中
frame.add(panel);
frame.setVisible(true);
//要关闭窗口,就要监听窗口关闭事件 System.exit(0)
//适配器模式 在匿名内部类中选择重写Closeing方法
frame.addWindowListener(new WindowAdapter() {
//在窗口关闭的时候需要做的事情
@Override
public void windowClosing(WindowEvent e) {
//关闭窗口
System.exit(0);
}
});
}
}
2.3、布局管理器
- 流式布局 FlowLayout
package org.star.demo;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestFlowLayout {
public static void main(String[] args) {
Frame frame = new Frame("FlowLayout");
//组件-按钮
Button button1 = new Button("button1");
Button button2 = new Button("button2");
Button button3 = new Button("button2");
//将按钮以流式布局的方式分布在窗口上 流式布局有左中右三种方式
//frame.setLayout(new FlowLayout());中间
//frame.setLayout(new FlowLayout(FlowLayout.LEFT));左
frame.setLayout(new FlowLayout(FlowLayout.RIGHT));//右
//设置大小 默认位置
frame.setSize(300, 400);
//添加按钮
frame.add(button1);
frame.add(button2);
frame.add(button3);
//可关闭窗口
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//可视化
frame.setVisible(true);
}
}
- 东南西北中 BorderLayout
package org.star.demo;
import java.awt.*;
public class TestBorderLayout {
public static void main(String[] args) {
Frame frame = new Frame("TestBorderLayout");
//BorderLayout有东南西北中五个方式
Button east = new Button("East");
Button west = new Button("West");
Button south = new Button("South");
Button north = new Button("North");
Button center = new Button("Center");
frame.add(east, BorderLayout.EAST);
frame.add(west, BorderLayout.WEST);
frame.add(south, BorderLayout.SOUTH);
frame.add(north, BorderLayout.NORTH);
frame.add(center, BorderLayout.CENTER);
frame.setBackground(Color.BLACK);
frame.setSize(300, 400);
frame.setVisible(true);
}
}
- 表格布局 GridLayout
package org.star.demo;
import java.awt.*;
public class TestGridLayout {
public static void main(String[] args) {
Frame frame = new Frame("GridLayout");
Button button1 = new Button("button1");
Button button2 = new Button("button2");
Button button3 = new Button("button3");
Button button4 = new Button("button4");
Button button5 = new Button("button5");
Button button6 = new Button("button6");
//表格式要new GridLayout后面的参数表示表格几行几列,后面还有两个参数表示行列间距,这里默认间距
//并且将表格格式使用setLatyou方法传入
frame.setLayout(new GridLayout(3, 2));
//添加按钮
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.add(button4);
frame.add(button5);
frame.add(button6);
//pack() Java函数是将按钮自动布局 可以不用
frame.pack();
frame.setSize(300, 400);
frame.setVisible(true);
frame.setBackground(Color.BLACK);
}
}
2.3.1、接下来做一个练习
创建一个如下的窗口,按钮如图所示
2.3.2、分析:这是一个窗口Frame,有上下两个面板(都是东西中布局),所以窗口是表格布局2X1,上面板的东西是两个按钮,中间是有两个按钮(表格布局2X1)的面板,下面板的的东西是两个按钮,中间是有4个按钮(表格布局2X2)的面板,所以需要1个Frame,4个Panel,10个Button。
2.3.3、代码实现:
package org.star.demo;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Test {
public static void main(String[] args) {
//总的窗口
Frame frame = new Frame("Test");
frame.setBounds(100, 100, 400, 400);
frame.setVisible(true);
frame.setLayout(new GridLayout(2, 1));//表格布局
//4个面板
Panel panel1 = new Panel();//上面板
Panel panel2 = new Panel();//上面板中的面板
Panel panel3 = new Panel();//下面板
Panel panel4 = new Panel();//下面板中的面板
//面板的布局
panel1.setLayout(new BorderLayout());//东南西北中
panel2.setLayout(new GridLayout(2, 1));//表格式
panel3.setLayout(new BorderLayout());//东南西北中
panel4.setLayout(new GridLayout(2, 2));//表格式
//按钮的添加
panel1.add(new Button("button1-1"), BorderLayout.WEST);//西
panel1.add(new Button("button1-2"), BorderLayout.EAST);//东
panel2.add(new Button("Center-button1-1"));//列表式是直接添加按钮,一个参数
panel2.add(new Button("Center-button1-2"));
panel3.add(new Button("button2-1"), BorderLayout.WEST);
panel3.add(new Button("button2-2"), BorderLayout.EAST);
for (int i = 0; i < 4; i++) {//这里使用循环添加四个按钮
panel4.add(new Button("Center-button2-" + i));
}
//分别将两个小面板添加到两个大面板
panel1.add(panel2, BorderLayout.CENTER);
panel3.add(panel4, BorderLayout.CENTER);
//分别将两个大面板添加到窗口
frame.add(panel1);
frame.add(panel3);
//关闭事件
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
2.3.4、运行结果:
2.4、事件监听
事件监听:当某个事情发生的时候,干什么?
package org.star.demo2;
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 TestActionEvent {
public static void main(String[] args) {
Frame frame = new Frame("TestActionEvent");
//我们设定按下按钮,发生事件
Button button = new Button("Action");
//按钮则需要调用addActionListener方法,查看源码,该方法需要传入一个ActionListener
//我们新建一个myActionListener类来继承ActionListener类,然后创建该类对象传入该方法
//或者使用匿名内部类
/*
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("abc");
}
});
*/
MyActionListener myActionListener = new MyActionListener();
button.addActionListener(myActionListener);
frame.add(button, BorderLayout.CENTER);//添加按钮
//关闭窗口的事件
windowClose(frame);
frame.setVisible(true);//可视化
frame.pack();
frame.setSize(300, 400);//设置大小
}
private static void windowClose(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
//事件监听
class MyActionListener implements ActionListener {
//继承ActionListener接口必须重写唯一的actionPerformed方法
@Override
public void actionPerformed(ActionEvent e) {
//这里输出abc
System.out.println("abc");
}
}
多个按钮共享一个事件
package org.star.demo2;
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("Test");
//两个按钮实现同一个事件监听
//比如开始和停止
Button button1 = new Button("start");
Button button2 = new Button("stop");
//给方法是设置按钮的信息,按钮1没有设置,则会显示默认的值
button2.setActionCommand("button2-stop");
MyMonitor myMonitor = new MyMonitor();
button1.addActionListener(myMonitor);
button2.addActionListener(myMonitor);
frame.add(button1, BorderLayout.NORTH);
frame.add(button2, BorderLayout.SOUTH);
frame.pack();
frame.setSize(300, 400);
frame.setVisible(true);
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());
//这里判断按钮的信息可以进行一些操作,实现按钮的通用
//即多个按钮共享一个事件,每个按钮分别进行一个操作
if (e.getActionCommand().equals("button2-stop")) {
System.exit(0);
}
}
}
2.5、输入框TextField监听
package org.star.demo2;
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 TestTextField {
public static void main(String[] args) {
//为了看起来更简介,我们创建其他的类来实现操作
//这里只需启动程序
new MyFrame();
}
}
class MyFrame extends Frame {//继承Frame类可以直接使用Frame方法
public MyFrame() {
//创建textField类添加到窗口
TextField textField = new TextField();
add(textField);
//文本框要输入文字则必须要监听这个文本框输入的文字
MyActionListener2 myActionListener2 = new MyActionListener2();
//按下enter就会触发这个输入框事件
textField.addActionListener(myActionListener2);
//我们也可以设置替换编码,在输入框中看不到真实的文本
textField.setEchoChar('*');
setVisible(true);
setSize(300, 400);
//关闭窗口
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class MyActionListener2 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//e.getSource()该方法时获得一些资源,返回的是一个对象
//将得到的对象转成TextField类
TextField field = (TextField) e.getSource();
//field.getText()获取输入框的文本
System.out.println(field.getText());//将输出输入框的文本
field.setText("");//将文本框清空
}
}
2.6、简易计算器
实现则这样一个简易计算器,两个文本框,一个加号标签,一个等号按钮,分别往两个文本框输入数字,按下按钮会将两个输入框中的数据相加输出到第三个文本框。
package org.star.demo2;
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 TestCalc {
public static void main(String[] args) {
//启动
new Calculator();
}
}
class Calculator extends Frame {
public Calculator() {
//3个文本框
TextField field1 = new TextField(10);//后面的参数为字符数
TextField field2 = new TextField(10);
TextField field3 = new TextField(20);
//一个标签
Label label = new Label("+");
//一个按钮
Button button = new Button("=");
MyCalculatorListener myCalculatorListener = new MyCalculatorListener(field1, field2, field3);
button.addActionListener(myCalculatorListener);
//布局
setLayout(new FlowLayout());//流式布局
add(field1);
add(label);
add(field2);
add(button);
add(field3);
pack();
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class MyCalculatorListener implements ActionListener {
private static TextField field1, field2, field3;
//利用构造方法将三个文本框传传入该类,利于操作
public MyCalculatorListener(TextField field1, TextField field2, TextField field3) {
this.field1 = field1;
this.field2 = field2;
this.field3 = field3;
}
@Override
public void actionPerformed(ActionEvent e) {
//获取文本框的数据
String text1 = field1.getText();
String text2 = field2.getText();
//String-->int
int num1 = Integer.parseInt(text1);
int num2 = Integer.parseInt(text2);
//将两个加数相加,并将结果以字符串的类型写到第三个文本框
int num3 = num1 + num2;
field3.setText(num3 + "");
//将前面两个框清除
field1.setText("");
field2.setText("");
}
}
完全改造为面向对象写法
package org.star.demo2;
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 TestCalc {
public static void main(String[] args) {
new MyCalculator().loadFrame();
}
}
class MyCalculator extends Frame {
TextField field1, field2, field3;
public void loadFrame() {
field1 = new TextField(10);
field2 = new TextField(10);
field3 = new TextField(20);
Label label = new Label("+");
Button button = new Button("=");
button.addActionListener(new CalcuatorListener(this));
setLayout(new FlowLayout());
add(field1);
add(label);
add(field2);
add(button);
add(field3);
pack();
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class CalcuatorListener implements ActionListener {
private static MyCalculator myCalculator = null;
public CalcuatorListener(MyCalculator myCalculator) {
this.myCalculator = myCalculator;
}
@Override
public void actionPerformed(ActionEvent e) {
String text1 = myCalculator.field1.getText();
String text2 = myCalculator.field2.getText();
int num1 = Integer.parseInt(text1);
int num2 = Integer.parseInt(text2);
myCalculator.field3.setText((num1 + num2) + "");
myCalculator.field1.setText("");
myCalculator.field2.setText("");
}
}
内部类:更好的包装
package org.star.demo3;
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 TextCalc {
public static void main(String[] args) {
new MyCalculator().loadFrame();
}
}
class MyCalculator extends Frame {
//属性
TextField field1, field2, field3;
//方法
public void loadFrame() {
field1 = new TextField(10);
field2 = new TextField(10);
field3 = new TextField(20);
Label label = new Label("+");
Button button = new Button("=");
button.addActionListener(new CalculatorListener());
setLayout(new FlowLayout());
add(field1);
add(label);
add(field2);
add(button);
add(field3);
pack();
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
//内部类可以访问外部类的属性个方法
class CalculatorListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int text1 = Integer.parseInt(field1.getText());
int text2 = Integer.parseInt(field2.getText());
field3.setText((text1 + text2) + "");
field1.setText("");
field2.setText("");
}
}
}
2.7、画笔
package org.star.demo3;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestPaint {
public static void main(String[] args) {
new MyPaint();
}
}
class MyPaint extends Frame {
public MyPaint() {
setBounds(100, 100, 400, 400);
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
//重写Frame类的paint方法
//画笔
@Override
public void paint(Graphics g) {
//画笔需要有颜色,画笔可以画画
//g.setColor(Color.red);//设置颜色
g.drawOval(100, 100, 100, 100);//画一个圆 参数是相对于窗口的位置,大小
g.fillOval(200, 100, 100, 100);//实心圆
g.drawRect(100, 200, 100, 100);//矩形
g.fillRect(200, 200, 100, 100);//实心矩形
//画笔用完,将它还原到最初的颜色,即将设置颜色代码注释掉
}
}
还原颜色后
2.8、鼠标监听
实现鼠标画画
package org.star.demo3;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Iterator;
//鼠标监听事件
public class TestMouseListener {
public static void main(String[] args) {
new MyFrame("TestMouse");
}
}
class MyFrame extends Frame {
//画画需要画笔,需要监听鼠标当前的位置,需要集合来存储这个点
ArrayList points;
public MyFrame(String title) {
super(title);//给窗口命名
setBounds(200, 200, 300, 400);
//存储鼠标点击的点
points = new ArrayList<Point>();
setVisible(true);
//鼠标监听器,正对这个窗口
addMouseListener(new MyMouseListener());
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
//画笔
@Override
public void paint(Graphics g) {
//画画,监听鼠标的事件
//遍历集合中的点,将点画上去
Iterator iterator = points.iterator();
while (iterator.hasNext()) {
Point point = (Point) iterator.next();
g.setColor(Color.BLUE);
//Point类中的方法:point.x,point.y 获取坐标
g.fillOval(point.x, point.y, 10, 10);//点是一个很小的实心圆
}
}
//适配器模式 在鼠标监听器中想重写哪一个方法就重写哪一个方法,不用重写所有的方法
private class MyMouseListener extends MouseAdapter {
//鼠标有:按下 弹起 按住不放几种
//该方法就是鼠标按压
//只需重写该方法
@Override
public void mousePressed(MouseEvent e) {
//MyFrame调用该类,所以得到的资源要转成MyFrame类型
MyFrame frame = (MyFrame) e.getSource();
//我们点击的时候,就会在界面上产生一个点!画
//e.getX(),e.getY是获得鼠标点击的点的坐标
//将鼠标点击的点存入集合points
points.add(new Point(e.getX(), e.getY()));
//每次点击都要重画一次
frame.repaint();//刷新
}
}
}
2.9、窗口监听
package org.star.demo3;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestWindow {
public static void main(String[] args) {
new WindowFrame();
}
}
class WindowFrame extends Frame {
public WindowFrame() {
setBounds(100, 100, 300, 400);
setVisible(true);
//使用匿名内类 适配器模式,可以选择方法进行重写
addWindowListener(new WindowAdapter() {
//关闭窗口
@Override
public void windowClosing(WindowEvent e) {
System.out.println("windowClosing");
System.exit(0);
}
//激活窗口
@Override
public void windowDeactivated(WindowEvent e) {
//当窗口最小化时就会执行
System.out.println("windowDeactivated");
}
});
}
}
2.10、键盘监听
package org.star.demo3;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestKeyListener {
public static void main(String[] args) {
new KeyFrame();
}
}
class KeyFrame extends Frame {
public KeyFrame() {
setVisible(true);
setBounds(100, 100, 300, 400);
//关闭窗口
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//键盘键听 同样使用适配器模式,重写想要的方法
addKeyListener(new KeyAdapter() {
//键盘按下
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();//获取按下键对应的ARCII码值
System.out.println(keyCode);
//KeyEvent.VK_XXX 可以得到所有的键
if (keyCode == KeyEvent.VK_E) {
System.out.println("你按下了E键");
}
}
});
}
}