GUI编程
GUI编程
组件:窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标 键盘事件 破解工具 ....
简介
GUI :Swing AWT
缺点:界面不美观 需要jre环境
但是我们可以从中了解MVC架构,了解监听
AWT
介绍:包含了很对类和接口
GUI:图形用户界面
元素:窗口 按钮 文本框

组件和容器
package javaSEStudy.guiDemo;
import java.awt.*;
//GUI的第一个界面
public class TestFrame {
public static void main(String[] args) {
//Frame
Frame frame = new Frame("我的第一个java图形界面窗口");
//需要设置可见性
frame.setVisible(true);
//设置窗口大小
frame.setSize(400, 400);
//设置背景颜色
frame.setBackground(new Color(87, 116, 182));
//弹出的最初位置
//屏幕最左上角就是0,0,0
frame.setLocation(200,200);
//设置大小固定
frame.setResizable(false);
}
}
问题:发现java窗口无法关闭,只能从断掉程序才能关闭窗口
尝试一次性打开多个窗口
package javaSEStudy.guiDemo;
import java.awt.*;
public class TestFrame2 {
public static void main(String[] args) {
//展示多个窗口
MyFrame myFrame1 = new MyFrame(100, 100, 200, 200, Color.BLUE);
MyFrame myFrame2 = new MyFrame(300, 100, 200, 200, Color.MAGENTA);
MyFrame myFrame3 = new MyFrame(100, 300, 200, 200, Color.RED);
MyFrame myFrame4 = new MyFrame(300, 300, 200, 200, Color.YELLOW);
}
}
class MyFrame extends Frame {
//可能存在多个窗口,我们需要一个计数器
static int id = 0;
public MyFrame(int x , int y,int w,int h,Color c) {
super("MyFrame"+(++id));
setVisible(true);
setBounds(x,y,w,h);
setBackground(c);
}
}
面板Panel
package javaSEStudy.guiDemo;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
//Panel 可以看作是一个空间,但是不能单独存在
public class TestFrame3 {
public static void main(String[] args) {
Frame frame = new Frame();
//布局的概念
Panel panel = new Panel();
//设置布局
frame.setLayout(null);
//坐标
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(87, 116, 182));
//panel设置坐标,相对于frame
panel.setBounds(50,50,100,100);
//panel设置属于自己的颜色
panel.setBackground(new Color(60, 175, 42));
//将Panel添加到frame当中
frame.add(panel);
frame.setVisible(true);
//监听事件,监听窗口关闭事件
//适配器模式
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
//窗口关闭时所需要做的事
//结束程序
System.exit(0);
}
});
}
}
解决了窗口关闭问题,加装了窗口关闭监听器,所以能关闭窗口
布局管理器
- 流式布局
FlowLayout
package javaSEStudy.guiDemo;
import java.awt.*;
//流式布局
public class TestFlowLayout {
public static void main(String[] args) {
Frame frame = new Frame();
//组件-按钮
Button button1 = new Button("button1");
Button button2 = new Button("button2");
Button button3 = new Button("button3");
//设置为流式布局
frame.setLayout(new FlowLayout(FlowLayout.LEFT));
//设置大小
frame.setSize(200, 200);
//把按钮添加上去
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.setVisible(true);
}
}
- 东西南北中
BorderLayout
package javaSEStudy.guiDemo;
import java.awt.*;
//东西南北中布局
public class TestBorderLayout {
public static void main(String[] args) {
Frame frame = new Frame("TestBorderLayout");
Button east = new Button("East");
Button wast = new Button("Wast");
Button south = new Button("South");
Button north = new Button("North");
Button center = new Button("Center");
frame.add(east, BorderLayout.EAST);
frame.add(wast, BorderLayout.WEST);
frame.add(south, BorderLayout.SOUTH);
frame.add(north, BorderLayout.NORTH);
frame.add(center, BorderLayout.CENTER);
frame.setVisible(true);
frame.setSize(400, 400);
}
}
- 表格式布局
GridLayout
package javaSEStudy.guiDemo.window;
import java.awt.*;
//表格式布局
public class TestGridLayout {
public static void main(String[] args) {
Frame frame = new Frame("TestGridLayout");
Button btn1 = new Button("btn1");
Button btn2 = new Button("btn2");
Button btn3 = new Button("btn3");
Button btn4 = new Button("btn4");
Button btn5 = new Button("btn5");
Button btn6 = new Button("btn6");
//三行两列
frame.setLayout(new GridLayout(3, 2));
frame.add(btn1);
frame.add(btn2);
frame.add(btn3);
frame.add(btn4);
frame.add(btn5);
frame.add(btn6);
//java函数,自动选择最优布局
frame.pack();
frame.setVisible(true);
frame.setSize(400, 400);
}
}
让我们来一个小练习
题目:

分析

分析完毕,那我们直接开始
package javaSEStudy.guiDemo.window;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
//一个小测试
public class Exercise {
public static void main(String[] args) {
//总窗口
Frame frame = new Frame();
frame.setLayout(new GridLayout(2,1));
frame.setSize(500,300);
//初始位置
frame.setLocation(200,200);
frame.setBackground(Color.green);
frame.setVisible(true);
//四个面板
Panel p1 = new Panel(new BorderLayout());
Panel p2 = new Panel(new GridLayout(2,1));
Panel p3 = new Panel(new BorderLayout());
Panel p4 = new Panel(new GridLayout(2,2));
//上面的按钮
p1.add(new Button("East-1"),BorderLayout.EAST);
p1.add(new Button("West-1"),BorderLayout.WEST);
p2.add(new Button("p2-btn-1"));
p2.add(new Button("p2-btn-2"));
p1.add(p2,BorderLayout.CENTER);
//下面的按钮
p3.add(new Button("East-2"),BorderLayout.EAST);
p3.add(new Button("West-2"),BorderLayout.WEST);
for (int i = 0; i < 4; i++) {
p4.add(new Button("for-"+i));
}
p3.add(p4,BorderLayout.CENTER);
frame.add(p1);
frame.add(p3);
//监听
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
最终运行结果:

总结
1.Frame是一个顶级窗口
2.Panel无法单独显示,必须添加到某个容器中
3.布局管理器Layout:
- 流式
- 东西南北中
- 表格
4.大小,定位,背景颜色,可见性,监听
事件监听
事件监听:当某个事情发生的时候,干什么?
我们直接来举个栗子
package javaSEStudy.guiDemo.action;
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 TeatAction1 {
public static void main(String[] args) {
//按下按钮触发一些事情
Frame frame = new Frame();
Button button = new Button();
//因为addActionListener()需要一个参数ActionListener,因此我们构造了一个ActionListener
MyActionListenner myActionListenner = new MyActionListenner();
button.addActionListener(myActionListenner);
//事件监听都可以用addActionListener()来做
frame.add(button,BorderLayout.CENTER);
//自适应
frame.pack();
//可见
frame.setVisible(true);
frame.setSize(200,200);
//关闭
windowClose(frame);
}
//关闭窗口的事件
private static void windowClose(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
//事件监听
class MyActionListenner implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("我也不知道按下这个按钮会发生什么");
}
}
多个按钮共享一个事件
我们直接上栗子
package javaSEStudy.guiDemo.action;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TeatAction2 {
public static void main(String[] args) {
// 两个按钮实现同一个监听
// 开始 停止
Frame frame = new Frame("strat - stop");
Button button1 = new Button("start");
Button button2 = new Button("stop");
//可以显示定义触发会返回的命令,如果不显示定义,则走默认的值
//多个按钮只写一个监听类
button2.setActionCommand("button2-stop");
button1.setActionCommand("button1-start");
MyMonitor myMonitor = new MyMonitor();
button1.addActionListener(myMonitor);
button2.addActionListener(myMonitor);
frame.add(button1,BorderLayout.SOUTH);
frame.add(button2,BorderLayout.NORTH);
frame.pack();
frame.setVisible(true);
frame.setSize(200,200);
}
}
class MyMonitor implements ActionListener {
//获得按钮上的信息
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按钮被点击了---->" + e.getActionCommand());
}
}
输入框TestField监听
package javaSEStudy.guiDemo.text;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test {
public static void main(String[] args) {
//main方法只管启动
MyFrame myFrame = new MyFrame();
}
}
class MyFrame extends Frame{
public MyFrame() {
TextField textField = new TextField();
add(textField);
//监听文本框输入的文字
MyActionListener actionListener = new MyActionListener();
//按下回车键就会触发这个输入框的事件
textField.addActionListener(actionListener);
//设置替换编码,也就是将其隐形
textField.setEchoChar('*');
pack();
setVisible(true);
setSize(200,200);
}
}
class MyActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//获得一些资源,也就是返回的一个对象
TextField field = (TextField) e.getSource();
//获得输入框中的文本
System.out.println(field.getText());
//获取到文本后将输入框清空
field.setText("");
}
}
简易计算器,组合+内部类回顾
OOP原则:组合 > 继承
class A extends B{
//这个为继承
}
Class A{
private B b;
//可避免产生很大的耦合性
//优先使用组合
}
我们直接来看简易计算器代码
package javaSEStudy.guiDemo.text;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//简易计算器
public class TestCalc {
public static void main(String[] args) {
new Calculator();
}
}
//计算器类
class Calculator extends Frame{
public Calculator(){
//需要三个文本框
//参数为文本最大能填多多少个字符
TextField num1 = new TextField(10);
TextField num2 = new TextField(10);
TextField num3 = new TextField(20);
//需要一个按钮
Button button = new Button("=");
//对他进行监听,按下等号即可相加
button.addActionListener(new MyCalculatorListener(num1,num2,num3));
//需要一个标签
//例如计算器的加号无任何意义,只是给看,他就是一个标签
//标签也可以是任何提示性内容
Label label = new Label("+");
//开始布局
setLayout(new FlowLayout());
add(num1);
add(label);
add(num2);
add(button);
add(num3);
pack();
setVisible(true);
}
}
//监听器类
class MyCalculatorListener implements ActionListener {
//获取三个变量
private TextField num1;
private TextField num2;
private TextField num3;
public MyCalculatorListener(TextField num1, TextField num2, TextField num3) {
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
}
@Override
public void actionPerformed(ActionEvent e) {
//获得加数和被加数
//num1是字符串类型,字符串转换为int类型用Integer
int n1 = Integer.parseInt(num1.getText());
int n2 = Integer.parseInt(num2.getText());
//将这个值进行加法运算后放入第三个框
num3.setText(""+(n1+n2));
//清除前两个框
num1.setText("");
num2.setText("");
}
}
改造为面向对象简易计算器代码
package javaSEStudy.guiDemo.text;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//使用面向对象的结构的简易计算器
public class TestCalcMax {
public static void main(String[] args) {
new Calculator1().loadFrame();
}
}
//计算器类
class Calculator1 extends Frame{
//属性
TextField num1;
TextField num2;
TextField num3;
//方法
public void loadFrame(){
//需要三个文本框
//参数为文本最大能填多多少个字符
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(20);
//需要一个按钮
Button button = new Button("=");
//对他进行监听,按下等号即可相加
//参数this就是他自己
button.addActionListener(new MyCalculatorListener1(this));
//需要一个标签
//例如计算器的加号无任何意义,只是给看,他就是一个标签
//标签也可以是任何提示性内容
Label label = new Label("+");
//开始布局
setLayout(new FlowLayout());
add(num1);
add(label);
add(num2);
add(button);
add(num3);
pack();
setVisible(true);
}
}
//监听器类
class MyCalculatorListener1 implements ActionListener {
//直接获取计算器这个对象
//在一个类中组合另外一个类
//空引用表示暂时不指向任何对象
Calculator1 calculator1 = null;
public MyCalculatorListener1(Calculator1 calculator1) {
this.calculator1 = calculator1;
}
@Override
public void actionPerformed(ActionEvent e) {
//获得加数和被加数
//将这个值进行加法运算后放入第三个框
//清除前两个框
int n1 = Integer.parseInt(calculator1.num1.getText());
int n2 = Integer.parseInt(calculator1.num2.getText());
calculator1.num3.setText(""+(n1+n2));
calculator1.num1.setText("");
calculator1.num2.setText("");
}
}
内部类
- 更好的包装
使用内部类对上面计算器进行改造
package javaSEStudy.guiDemo.text;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//使用内部类制作的简易计算器
public class TestCalcProMax {
public static void main(String[] args) {
new Calculator1().loadFrame();
}
}
//计算器类
class Calculator2 extends Frame{
//属性
TextField num1;
TextField num2;
TextField num3;
//方法
public void loadFrame(){
//需要三个文本框
//参数为文本最大能填多多少个字符
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(20);
//需要一个按钮
Button button = new Button("=");
//对他进行监听,按下等号即可相加
//参数this就是他自己
button.addActionListener(new MyCalculatorListener2());
//需要一个标签
//例如计算器的加号无任何意义,只是给看,他就是一个标签
//标签也可以是任何提示性内容
Label label = new Label("+");
//开始布局
setLayout(new FlowLayout());
add(num1);
add(label);
add(num2);
add(button);
add(num3);
pack();
setVisible(true);
}
//监听器类
//内部类最大的好处,就是可以畅通无阻的访问外部的属性和方法
private class MyCalculatorListener2 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//获得加数和被加数
//将这个值进行加法运算后放入第三个框
//清除前两个框
int n1 = Integer.parseInt(num1.getText());
int n2 = Integer.parseInt(num2.getText());
num3.setText(""+(n1+n2));
num1.setText("");
num2.setText("");
}
}
}
画笔Paint
简单了解一下画笔
package javaSEStudy.guiDemo.paint;
import org.apache.commons.io.FileUtils;
import java.awt.*;
public class TestPaint {
public static void main(String[] args) {
new MyPaint().loadFrame();
}
}
class MyPaint extends Frame{
public void loadFrame(){
setVisible(true);
setBounds(100,100,800,600);
}
//画笔
@Override
public void paint(Graphics g) {
//画笔需要有颜色,画笔可以画画
g.setColor(Color.BLACK);
//画个圆
g.drawOval(100,100,100,100);
//画个实心圆
g.fillOval(300,300,100,100);
g.setColor(Color.RED);
//画个实心矩形
g.fillRect(200,200,50,50);
//养成习惯,画笔用完将他还原到最初的颜色-->黑色
}
}
鼠标监听
目的:想要实现鼠标画画
package javaSEStudy.guiDemo.paint;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
//鼠标监听事件
public class TestMouse {
public static void main(String[] args) {
new MyFrame("darw");
}
}
//自己的类
class MyFrame extends Frame{
//画画需要画笔,需要监听鼠标当前位置,需要个集合存储这些点
ArrayList points;
public MyFrame(String title){
super(title);
setBounds(200,200,700,400);
//存鼠标点击的点
points = new ArrayList<>();
setVisible(true);
//鼠标监听器,针对这个窗口
this.addMouseListener(new MouseListener());
}
@Override
public void paint(Graphics g) {
//画画,需要监听鼠标的事件
Iterator iterator = points.iterator();
while (iterator.hasNext()) {
Point point = (Point) iterator.next();
g.setColor(Color.red);
g.fillOval(point.x,point.y,10,10);
}
}
//添加一个点到界面上
public void addPoint(Point point){
points.add(point);
}
//适配器模式
private class MouseListener extends MouseAdapter {
//鼠标:按下,弹起,按住不放
@Override
public void mousePressed(MouseEvent e) {
//返回当前对象
MyFrame frame = (MyFrame) e.getSource();
//当我们点击的时候就会在屏幕上产生一个点
//这个点就是鼠标的点
frame.addPoint( new Point(e.getX(),e.getY()));
//每次点击鼠标都需要它重新画一次
//刷新
frame.repaint();
}
}
}
联系

窗口监听
package javaSEStudy.guiDemo.paint;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
//窗口监听事件
public class TestWindow {
public static void main(String[] args) {
new WindowFrame();
}
}
class WindowFrame extends Frame{
public WindowFrame(){
setVisible(true);
setBackground(Color.GREEN);
setBounds(100,100,300,200);
addWindowListener(new WindowListener());
/*
匿名内部类,最好使用该方式
this.addWindowListener(
new WindowAdapter(){
@Override
public void WindowClsoing(WindowEvent e){
super.windowClosing(e);
}
}
*/
}
//窗口监听器
class WindowListener extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e){
//隐藏窗口,通过按钮,隐藏当前窗口
setVisible(false);
//exit 是正常退出
System.exit(0);
}
}
}
class Window implements WindowListener{
//只有激活和关闭才是最常用且能被监听到的
@Override
public void windowOpened(WindowEvent e) {
//窗口已打开
}
@Override
public void windowClosing(WindowEvent e) {
//窗口正在关闭
}
@Override
public void windowClosed(WindowEvent e) {
//窗口已关闭
}
@Override
public void windowIconified(WindowEvent e) {
//最小化,图标化
}
@Override
public void windowActivated(WindowEvent e) {
//激活 当鼠标移开窗口或焦点不在该程序内,无法对其操作,只有鼠标点击程序后激活才能使用
}
@Override
public void windowDeiconified(WindowEvent e) {
//取消图标化,从最小化到正常状态
}
@Override
public void windowDeactivated(WindowEvent e) {
//用于处理窗口失去焦点(变为非活动状态)的事件,例如视频暂停播放,音乐停止
}
}
键盘监听
package javaSEStudy.guiDemo.paint;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
//键盘监听事件
public class TestKeyListener {
public static void main(String[] args) {
new keyFrame();
}
}
class keyFrame extends Frame {
public keyFrame(){
setBounds(100,100,500,500);
setVisible(true);
this.addKeyListener(new KeyAdapter() {
//键盘按下
@Override
public void keyPressed(KeyEvent e) {
//获得键盘按下的键是哪一个
//获得键盘值
int keyCode = e.getKeyCode();
//不需要去记录这个值,直接用静态属性 VK_XXX
if(keyCode == KeyEvent.VK_ENTER){
System.out.println("你按下了回车键");
}
//根据按下的不同的操作产生不同的结果
}
});
}
}
Swing
JFrame:窗口,面板
setDefaultCloseOperation 是 Java Swing 中 JFrame 类的一个方法,用于设置窗口关闭按钮(×)的默认行为
| 参数值 | 常量名 | 行为描述 |
|---|---|---|
| 0 | DO_NOTHING_ON_CLOSE | 点击关闭按钮时无任何反应(需手动监听关闭事件处理) |
| 1 | HIDE_ON_CLOSE | 默认值,隐藏窗口(程序仍在后台运行) |
| 2 | DISPOSE_ON_CLOSE | 释放窗口资源(若所有窗口被释放,程序可能退出) |
| 3 | EXIT_ON_CLOSE | 直接终止程序(System.exit(0) ) |
简单创建一个JFrame窗口
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
public class JFrameDemo {
//init 初始化的方法
public void init(){
//JFrame 是一个顶级窗口
JFrame jf = new JFrame("这是一个JFrame窗口");
jf.setVisible(true);
jf.setBounds(100, 100, 450, 300);
//这个写法无法正确输出颜色
jf.setBackground(Color.GREEN);
//设置文字
JLabel label = new JLabel("欢迎来到基尼太美");
jf.add(label);
//让我们的文本标签居中
// 设置水平对齐 常量
label.setHorizontalAlignment(SwingConstants.CENTER);
//容器实例化
Container cp = jf.getContentPane();
//这样才能让颜色正确输出
cp.setBackground(Color.GREEN);
//关闭事件 设置窗口关闭按钮 常量 操作
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
//创建一个窗口
new JFrameDemo().init();
}
}
弹窗
dialog:用来被弹出,默认就有关闭方法
首先来说说这两句代码的区别
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
| 写法 | 来源 | 适用场景 | 代码示例 |
|---|---|---|---|
| JFrame.EXIT_ON_CLOSE | JFrame 类的静态常量 | 直接在 JFrame 对象上调用时更直观 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
| WindowConstants.EXIT_ON_CLOSE | WindowConstants 接口常量 | 通用性更强,适用于所有实现 WindowConstants 的类(如 JDialog) | dialog.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); |
我们来举个栗子
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//主窗口
public class DialogDemo extends JFrame {
public DialogDemo() {
this.setVisible(true);
this.setSize(500, 300);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//JFrame 放东西需要容器
Container cp = this.getContentPane();
//绝对布局
cp.setLayout(null);
//按钮
JButton button = new JButton("点击弹出一个对话框");
button.setBounds(10, 10, 100, 30);
//点击这个按钮的时候弹出一个弹窗
button.addActionListener(new ActionListener() {
//这是监听器
@Override
public void actionPerformed(ActionEvent e) {
//弹窗
new MyDialog();
}
});
cp.add(button);
}
public static void main(String[] args) {
new DialogDemo();
}
}
//弹窗的窗口
class MyDialog extends JDialog {
public MyDialog() {
this.setVisible(true);
this.setBounds(100, 100, 300, 300);
//弹窗自带关闭方法,不需要我们再去设置
// this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
Container container = this.getContentPane();
container.setLayout(null);
container.add(new Label("蔡徐坤带你学java"));
}
}
标签
label
new JLabel("XXX");
将其升级为图标ICON
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
//图标,需要实现类,Frame继承
public class IconDemo extends JFrame implements Icon {
private int width;
private int height;
//无参构造
public IconDemo() {
}
public IconDemo(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
g.fillOval(x, y, width, height);
}
@Override
public int getIconWidth() {
return this.width;
}
@Override
public int getIconHeight() {
return this.height;
}
public void init(){
IconDemo icon = new IconDemo(50, 50);
//图标会放在标签上,也可以放在按钮上
JLabel label = new JLabel("Icon Demo", icon, SwingConstants.CENTER);
Container container = getContentPane();
container.add(label);
this.setVisible(true);
this.setSize(500, 300);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new IconDemo().init();
}
}
在实际开发中我们并不会去让java帮我们画一个图标,而是去用一个小图片去替代这个图标,所以我们就来到了
图片图标
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class ImageIconDemo extends JFrame{
public ImageIconDemo() {
//获取图片的地址
//在同一个文件夹内,通过这个类去获取
JLabel label = new JLabel("image");
URL tx = ImageIconDemo.class.getResource("tb.png");
//注意命名冲突
ImageIcon icon = new ImageIcon(tx);
label.setIcon(icon);
//居中显示
label.setHorizontalAlignment(SwingConstants.CENTER);
Container container = getContentPane();
container.add(label);
setVisible(true);
setSize(500, 500);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new ImageIconDemo();
}
}
PS:注意将我图片名字换成你自己的,这是通过类名去获取图片,类名也得是该图片名字
面板
Jpanel
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
//面板
public class JpanelDemo extends JFrame {
public JpanelDemo() {
Container container = this.getContentPane();
//末尾10参数指的是上下间距
container.setLayout(new GridLayout(2,1,10,10));
JPanel panel1 = new JPanel(new GridLayout(1,3));
JPanel panel2 = new JPanel(new GridLayout(1,2));
JPanel panel3 = new JPanel(new GridLayout(2,1));
JPanel panel4 = new JPanel(new GridLayout(3,2));
panel1.add(new JButton("1"));
panel1.add(new JButton("1"));
panel1.add(new JButton("1"));
panel2.add(new JButton("2"));
panel2.add(new JButton("2"));
panel3.add(new JButton("3"));
panel3.add(new JButton("3"));
panel4.add(new JButton("4"));
panel4.add(new JButton("4"));
panel4.add(new JButton("4"));
panel4.add(new JButton("4"));
panel4.add(new JButton("4"));
panel4.add(new JButton("4"));
container.add(panel1);
container.add(panel2);
container.add(panel3);
container.add(panel4);
this.setVisible(true);
this.setSize(300,300);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JpanelDemo();
}
}
滚动条:
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
//滚动条
public class JScrollPanelDemo extends JFrame {
public JScrollPanelDemo() {
Container container = this.getContentPane();
//文本域
JTextArea textArea = new JTextArea(20,50);
textArea.setText("This is a JTextArea demo");
//Scroll面板
JScrollPane scrollPane = new JScrollPane(textArea);
container.add(scrollPane);
this.setVisible(true);
this.setSize(300, 300);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JScrollPanelDemo();
}
}
按钮
JButton
这是一个普通的图片按钮
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class JButtonDemo01 extends JFrame {
public JButtonDemo01() {
Container container = this.getContentPane();
//将一个图片变为一个图标
URL resource = JButtonDemo01.class.getResource("tb.png");
ImageIcon icon = new ImageIcon(resource);
//把这个图标放在按钮上
JButton button = new JButton();
button.setIcon(icon);
//当鼠标悬浮在图片上时显示的内容
button.setToolTipText("这是一个图片按钮");
//添加
container.add(button);
this.setVisible(true);
this.setSize(300, 300);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JButtonDemo01();
}
}
单选按钮
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
//单选框
public class JButtonDemo02 extends JFrame {
public JButtonDemo02() {
Container container = this.getContentPane();
//单选框
JRadioButton jb1 = new JRadioButton("JRadioButton1");
JRadioButton jb2 = new JRadioButton("JRadioButton2");
JRadioButton jb3 = new JRadioButton("JRadioButton3");
//由于单选框不能被同时选择,所以我们用分组实现该功能,一个组中只能选择一个
ButtonGroup bg = new ButtonGroup();
bg.add(jb1);
bg.add(jb2);
bg.add(jb3);
//上中下布局
container.add(jb1, BorderLayout.NORTH);
container.add(jb2, BorderLayout.CENTER);
container.add(jb3, BorderLayout.SOUTH);
this.setVisible(true);
this.setSize(300, 300);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JButtonDemo02();
}
}
多选按钮
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
//单选框
public class JButtonDemo03 extends JFrame {
public JButtonDemo03() {
Container container = this.getContentPane();
//多选框
JCheckBox box1 = new JCheckBox("box1");
JCheckBox box2 = new JCheckBox("box2");
container.add(box1, BorderLayout.NORTH);
container.add(box2, BorderLayout.SOUTH);
this.setVisible(true);
this.setSize(300, 300);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JButtonDemo03();
}
}
列表
- 下拉框
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
//下拉框
public class ComboboxDemo extends JFrame {
public ComboboxDemo() {
Container container = this.getContentPane();
JComboBox status = new JComboBox<>();
//item 项目,商品
status.addItem(null);
status.addItem("正在热映");
status.addItem("已下架");
status.addItem("即将上映");
//获取监听器
// status.addActionListener();
container.add(status);
this.setSize(200, 60);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new ComboboxDemo();
}
}
- 列表框
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
import java.util.Vector;
//列表框
public class ComboboxDemo2 extends JFrame {
public ComboboxDemo2() {
Container container = this.getContentPane();
//生成列表的内容 静态生成一个数组
// String[] contents = {"1","2","3"};
/*
Vector:是 Java 集合框架中一个经典的线程安全动态数组实现
线程安全实现
所有方法都用 synchronized 修饰
适合多线程环境但单线程性能较低
现代开发中常被 Collections.synchronizedList() 包装的 ArrayList 替代
动态扩容机制
默认初始容量为10
扩容策略:当超出容量时默认增长为原来的2倍
可通过 capacityIncrement 构造参数自定义增量
增删改查
addElement(E obj) // 等效于 add()
removeElement(Object obj)
setElementAt(E obj, int index)
elementAt(int index) // 等效于 get()
特有方法
firstElement() // 获取首元素
lastElement() // 获取末元素
elements() // 返回Enumeration(旧式迭代器)
*/
Vector contents = new Vector();
//列表中需要放内容
JList list = new JList(contents);
contents.add("张三");
contents.add("李四");
contents.add("王五");
container.add(list);
this.setSize(200, 100);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new ComboboxDemo2();
}
}
应用场景
- 选择地区,或者一些单个选项(选项只有两个使用单选框按钮,超过两个使用下拉框,节省内存布局)
- 列表:展示一些信息,一般是动态扩容
文本框
- 文本框
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
//文本框
public class TextTest1 extends JFrame {
public TextTest1() {
Container container = this.getContentPane();
//""内为初始默认显示内容,20设定默认字符大小
JTextField text1 = new JTextField("hello ");
JTextField text2 = new JTextField("world",20);
container.add(text1,BorderLayout.NORTH);
container.add(text2,BorderLayout.SOUTH);
this.setSize(200, 60);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new TextTest1();
}
}
- 密码框
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
//密码框
public class TextTest2 extends JFrame {
public TextTest2() {
//默认使用东西南北布局,我们最好使用面板去做
Container container = this.getContentPane();
//默认显示为 ..... 这种小黑点
JPasswordField passworld = new JPasswordField();
//将输入字符显示为小黑点,这里我们改为****
passworld.setEchoChar('*');
container.add(passworld);
this.setSize(200, 60);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new TextTest2();
}
}
- 文本域
一般配合面板使用.超过显示内容自动往下,然后使用滚动条进行上下操作
package javaSEStudy.guiDemo.swing;
import javax.swing.*;
import java.awt.*;
//滚动条
public class JScrollPanelDemo extends JFrame {
public JScrollPanelDemo() {
Container container = this.getContentPane();
//文本域
JTextArea textArea = new JTextArea(20,50);
textArea.setText("This is a JTextArea demo");
//Scroll面板
JScrollPane scrollPane = new JScrollPane(textArea);
container.add(scrollPane);
this.setVisible(true);
this.setSize(300, 300);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JScrollPanelDemo();
}
}
贪吃蛇
帧 :如果时间片足够小就是动画,一秒30帧,60帧
连起来是动画,拆开就是静态图片
.equals才是正确字符串比较方式
| 场景 | 应使用 |
|---|---|
| 基本类型值比较 | == |
| 判断两个引用是否指向同一对象 | == |
| 判断两个对象内容是否相同 | equals |
| 避免空指针的比较 | Objects.equals() |
键盘监听
定时器 Timer
做完该代码步骤
- 1.定义数据
- 2.画上去
- 3.监听事件
- 键盘
- 事件
先将启动类写出
package javaSEStudy.guiDemo.snake;
import javax.swing.*;
//游戏的启动类
public class StartGame {
public static void main(String[] args) {
JFrame frame = new JFrame();
//这里窗口大小不能改变,固定大小,任意改变会导致游戏出错
frame.setBounds(300,80,900,720);
//窗口大小不可变
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//正常的游戏界面应该在面板上
frame.add(new GamePanel());
frame.setVisible(true);
}
}
再建立一个数据中心,存放用到的图片
package javaSEStudy.guiDemo.snake;
import javax.swing.*;
import java.net.URL;
//数据中心
public class Data {
public static URL handerURl = Data.class.getResource("statics/header.png");
public static ImageIcon hander = new ImageIcon(handerURl);
public static URL bodyURl = Data.class.getResource("statics/body.png");
public static ImageIcon body = new ImageIcon(bodyURl);
public static URL foodURl = Data.class.getResource("statics/food.png");
public static ImageIcon food= new ImageIcon(foodURl);
public static URL upURl = Data.class.getResource("statics/up.png");
public static URL downURl = Data.class.getResource("statics/down.png");
public static URL leftURl = Data.class.getResource("statics/left.png");
public static URL rightURl = Data.class.getResource("statics/right.png");
public static ImageIcon up = new ImageIcon(upURl);
public static ImageIcon down = new ImageIcon(downURl);
public static ImageIcon left = new ImageIcon(leftURl);
public static ImageIcon right = new ImageIcon(rightURl);
}
最后把游戏写出
package javaSEStudy.guiDemo.snake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
//游戏面板
public class GamePanel extends JPanel implements KeyListener, ActionListener {
//定义蛇的数据结构
//蛇的长度
int length;
//蛇的x坐标 25*25
int[] snakeX = new int[600];
//蛇的y坐标 25*25
int[] snakeY = new int[500];
//定义蛇的方向
String direction;
//食物的坐标
int foodX;
int foodY;
Random random = new Random();
//积分
int score;
//游戏当前状态:开始,停止
//默认是不开始
boolean isStart = false;
//默认不失败
boolean isEnd = false;
//定时器
//100毫秒执行一次
//以毫秒为单位,1000ms = 1s
Timer timer = new Timer(100, this);
//构造器
public GamePanel() {
init();
//获得焦点
this.setFocusable(true);
//获得键盘监听事件
this.addKeyListener(this);
//游戏一开始定时器启动
timer.start();
}
//初始化方法
public void init(){
length = 3;
//头部位置
snakeX[0] = 100;snakeY[0] = 100;
//第一个身体的坐标
snakeX[1] = 75;snakeY[1] = 100;
//第二个身体的坐标
snakeX[2] = 50;snakeY[2] = 100;
//初始化方法向右
direction= "R";
//把食物随机分布到界面上
foodX = 25 + 25*random.nextInt(34);
foodY = 75 + 25*random.nextInt(24);
//初始化积分
score = 0;
}
//绘制面板,我们游戏中的所有东西都使用这个画笔绘制
@Override
protected void paintComponent(Graphics g) {
//清屏,如果不用会导致界面闪烁
super.paintComponent(g);
//绘制静态的面板
this.setBackground(Color.white);
//绘制头部广告位
Data.hander.paintIcon(this,g,25,11);
//绘制一个矩形,让小蛇在上面跑,也就是默认的游戏界面
g.fillRect(25,75,850,600);
//绘制积分
g.setColor(Color.white);
g.setFont(new Font("仿宋",Font.BOLD,20));
g.drawString("长度"+length,750,35);
g.drawString("分数"+score,750,60);
//绘制食物
Data.food.paintIcon(this,g,foodX,foodY);
//把小蛇画上去
if (direction.equals("R")) {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
}else if(direction.equals("L")) {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
}else if(direction.equals("U")) {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
}else if(direction.equals("D")) {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
}
//for循环去重复绘制越来越长的身体
for (int i = 1; i < length; i++) {
Data.body.paintIcon(this,g,snakeX[i], snakeY[i]);
}
//游戏状态
if (isStart == false) {
g.setColor(Color.white);
//设置字体
g.setFont(new Font("仿宋",Font.BOLD,40));
g.drawString("按下空格开始游戏",300,300 );
}
if (isEnd) {
g.setColor(Color.red);
//设置字体
g.setFont(new Font("仿宋",Font.BOLD,40));
g.drawString("游戏结束,按下空格重新开始",300,300 );
}
}
//键盘监听器
//键盘按压
@Override
public void keyPressed(KeyEvent e) {
//获得键盘的按键
int keyCode= e.getKeyCode();
//
if (keyCode == KeyEvent.VK_SPACE){
//先判断游戏是否结束
if(isEnd){
//如果游戏失败为真,则按空格重新开始
isEnd = false;
init();
}else{
//取反,不能写死,否则空格没用
isStart =! isStart;
}
//刷新操作
repaint();
}
//小蛇移动
if(keyCode==KeyEvent.VK_UP){
direction = "U";
} else if (keyCode==KeyEvent.VK_DOWN) {
direction = "D";
}else if (keyCode==KeyEvent.VK_LEFT) {
direction = "L";
}else if (keyCode==KeyEvent.VK_RIGHT) {
direction = "R";
}
}
//事件监听--->需要通过固定的事件来刷新,1秒10次
@Override
public void actionPerformed(ActionEvent e) {
if (isStart && isEnd == false) {
//吃食物
if(snakeX[0] == foodX && snakeY[0] == foodY){
//长度+1
length++;
//分数+10
score += 10;
//再次随机生成食物
foodX = 25 + 25*random.nextInt(34);
foodY = 75 + 25*random.nextInt(24);
}
//如果游戏是开始状态,就让小蛇动起来
//身体右移,后一节移到前一节位置 snakeX[1] = snakeX[0]
for (int i = length - 1; i > 0; i--) {
//向前移动一节
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
//控制走向
if (direction.equals("R")) {
//头部右移
snakeX[0] = snakeX[0] + 25;
//边界判断
if (snakeX[0] > 850) {snakeX[0] = 25;}
} else if (direction.equals("L")) {
//头部左移
snakeX[0] = snakeX[0] - 25;
//边界判断
if (snakeX[0] < 25) {snakeX[0] = 850;}
} else if (direction.equals("U")) {
//头部上移
snakeY[0] = snakeY[0] - 25;
//边界判断
if (snakeY[0] < 75) {snakeY[0] = 650;}
}else if (direction.equals("D")) {
//头部下移
snakeY[0] = snakeY[0] + 25;
//边界判断
if (snakeX[0] > 650) {snakeX[0] = 75;}
}
//失败事件,撞到自己
for (int i = 1; i < length; i++) {
if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
isEnd = true;
}
}
//重画页面
repaint();
}
//定时器开始
timer.start();
}
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {}
}
小结

浙公网安备 33010602011771号