JavaGUI编程

Posted woodwhale

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaGUI编程相关的知识,希望对你有一定的参考价值。

GUI编程

前言

任务罢了,好在狂神老师居然有GUI的课,只能说是有救星了。

【狂神说Java】GUI编程入门到游戏实战

1、了解GUI

组建:

  • 窗口
  • 弹窗
  • 面板
  • 文本框
  • 列表框
  • 按钮
  • 图片
  • 监听事件
  • 鼠标
  • 键盘事件
  • (狂神老师提到逆向破解游戏基本使用java来写

2、简介

GUI的核心:

Swing AWT

为什么javaGUI不流行?

  • 界面丑
  • 需要jre环境

那么为什么要学?

  • 自制工具(确实,ctf许多工具都是用javaGUI写成打包的jar
  • 极小概率在工作中维护Swing界面(大概我这辈子见不到了吧
  • 重点是学习监听事件,可以由此了解MVC架构

3、AWT

3.1 AWT介绍

用于GUI编程,AWT就是抽象窗口工具

(Eclipse和IDEA就是用java Swing写出来的)

  1. 包含了很多类和接口
  2. 包含了很多元素:窗口、按钮、文本框
  3. 在java.awt包中

3.2 组件和容器

1、Frame

我们现来看看第一个frame

package top.woodwhale.study;

import java.awt.*;

// GUI的第一个界面
public class TestFrame {
    public static void main(String[] args) {

        // Frame
        Frame frame = new Frame("First Java Window");

        // 需要设置可见性,长度、宽度
        frame.setVisible(true);
        frame.setSize(400,400);

        // 设置背景颜色 Color
        frame.setBackground(new Color(22, 87, 220));

        // 弹出的初始位置
        frame.setLocation(200,200);

        // 设置大小固定
        frame.setResizable(false);
    }
}

效果就是一个蓝色的、不可拉伸、不可关闭的窗口

思考:

  • 为什么无法关闭?
  • 如何让窗口关闭?只能靠关闭程序吗?

如果我们需要同时开启多个窗口,有没有什么好的方法呢?

  • 可以写一个自类,继承自Frame,然后实现我们需要的功能
package top.woodwhale.study;

import java.awt.*;

public class TestFrame2 {
    public static void main(String[] args) {

        // 展示多个窗口
        MyFrame mf1 = new MyFrame(100,100,200,200,Color.black);
        MyFrame mf2 = new MyFrame(300,100,200,200,Color.orange);
        MyFrame mf3 = new MyFrame(100,300,200,200,Color.green);
        MyFrame mf4 = new MyFrame(300,300,200,200,Color.pink);
    }
}
class MyFrame extends Frame{
    static int id = 0;  // 可能存在多个窗口,需要一个计数器

    public MyFrame(int x,int y,int w,int h,Color color) {
        super("Myframe"+ (++id));
        setBackground(color);
        setBounds(x,y,w,h);
        setVisible(true);
    }
}

效果如下:(有点好看

2、Panel

面板Panel可以看成是一个空间,但是不能单独存在,可以存在与一个框架中。类似于前段的div(大概

以下的例子通过适配器模式来监听窗口关闭事件

package top.woodwhale.study;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class TestPanel {
    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(40,161,35));
        // 面板设置坐标,相对于frame
        panel.setBounds(50,50,400,400);
        panel.setBackground(new Color(190,15,60));
        // frame.add()
        frame.add(panel);
        // 将面板设置为可见
        frame.setVisible(true);

        // 监听窗口关闭事件
        // 适配器模式:
        frame.addWindowListener(new WindowAdapter() {
            // 窗口点击关闭的时候需要做的事情
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
}

效果如下:(我们点击关闭按钮可以结束进程,也就是退出

3、布局管理

  • 流式布局

    这个按钮的年代感直接出来了,有种wine打开exe的味道了

    package top.woodwhale.study;
    
    import java.awt.*;
    
    public class TestFlowLayout {
        public static void main(String[] args) {
            Frame frame = new Frame("114514");
    
            // 组件-按钮
            Button button1 = new Button("button1");
            Button button2 = new Button("button2");
            Button button3 = new Button("button3");
    
            // 设置为流式布局 默认是居中
            frame.setLayout(new FlowLayout());
    //        frame.setLayout(new FlowLayout(FlowLayout.RIGHT));
    
            frame.setSize(200,200);
    
            // 把按钮添加上去
            frame.add(button1);
            frame.add(button2);
            frame.add(button3);
    
            frame.setVisible(true);
        }
    }
    
  • 东西南北中

    狂神老师说这是视频软件的布局,为什么我第一反应是,上下左右都是广告,中间是小视频(bushi

    package top.woodwhale.study;
    
    import java.awt.*;
    
    public class TestBorderLayout {
        public static void main(String[] args) {
            Frame frame = new Frame("114514");
            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.setSize(300,300);
            frame.setVisible(true);
        }
    }
    
  • 表格布局

    就是类似表格的形式,这里使用了pack()方法来使大小、内容自动填充

    package top.woodwhale.study;
    
    import java.awt.*;
    
    public class TestGridLayout {
        public static void main(String[] args) {
            Frame frame = new Frame("114514");
            Button bt1 = new Button("bt1");
            Button bt2 = new Button("bt2");
            Button bt3 = new Button("bt3");
            Button bt4 = new Button("bt4");
            Button bt5 = new Button("bt5");
            Button bt6 = new Button("bt6");
    
            frame.setLayout(new GridLayout(3,2));
            frame.add(bt1);
            frame.add(bt2);
            frame.add(bt3);
            frame.add(bt4);
            frame.add(bt5);
            frame.add(bt6);
    
            frame.pack();   // java方法,用来自动填充
            frame.setVisible(true);
    
        }
    }
    

4、狂神老师的作业time

如何完成下图的格式布局?

直接动手

动手之前先进行构思,一个好的项目,构思占据80%,代码只有20%!!!

我们现构建一个两行一列的frame,然后在中间部分上下各设置一个面板,frame的上半部分和下半部分都使用东西南北中的布局管理,再在两个面板中设置东西南北中格式,其中上面的嵌套一个两行一列的面板,下面的嵌套一个两行两列的面板

最终效果:

代码:

package top.woodwhale.study;

import java.awt.*;
import java.awt.image.ImageObserver;

public class MyLayout {
    public static void main(String[] args) {
        Frame frame = new Frame("114514");

        frame.setSize(400,300);
        frame.setLocation(300,300);
        frame.setBackground(Color.orange);
        frame.setVisible(true);

        // 两行一列
        frame.setLayout(new GridLayout(2,1));

        // 4个面板
        Panel panel1 = new Panel(new BorderLayout());
        Panel panel2 = new Panel(new GridLayout(2,1));
        Panel panel3 = new Panel(new BorderLayout());
        Panel panel4 = new Panel(new GridLayout(2,2));

        panel1.add(new Button("East-1"),BorderLayout.EAST);
        panel1.add(new Button("West-1"),BorderLayout.WEST);

        panel2.add(new Button("p2-btn-1"));
        panel2.add(new Button("p2-btn-2"));

        panel1.add(panel2,BorderLayout.CENTER);

        panel3.add(new Button("East-2"),BorderLayout.EAST);
        panel3.add(new Button("West-2"),BorderLayout.WEST);

        for (int i = 0; i < 4; i++) {
            panel4.add(new Button("for-"+i));
        }
        panel3.add(panel4,BorderLayout.CENTER);

        frame.add(panel1);
        frame.add(panel3);
    }
}

5、总结

  1. Frame是一个顶级窗口
  2. Panel无法单独显示,得放入Frame(容器)中
  3. 布局管理
    • 流式
    • 东西南北中
    • 表格
  4. 设置大小、定位、背景、监听
  5. 设计模式不要直接写,先去构想!

3.3 监听事件

1、监听测试

监听就是,当发生某事件后,我们监听到了这个动态,应该有某种反馈

先来点效果图:

可以观察到,我们第一次这个巨大按钮,就会在控制台输出一次114514,这是为啥呢?

package top.woodwhale.study2;

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();

        // 按下按钮的时候,触发一些事件
        Button button = new Button("点我控制台输出114514");

        // 因为addActionListener需要一个ActionListener,所以我们字节写一个MyActionListener类
        MyActionListener myActionListener = new MyActionListener();
        button.addActionListener(myActionListener);

        frame.add(button);
        frame.setSize(300,300);
        frame.setVisible(true);
        windowClose(frame);
    }

    // 关闭窗口事件
    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 actionEvent) {
        System.out.println("114514");
    }
}

其实是因为,我们设置了一个按钮的监听器,我们自己写了一个MyActionListener类,是ActionListener的一个接口,我们重写的方法就是只要有这个事件产生,就输出114514。

而我们在button中使用了addActionListener方法,将我们重写的监听器赋予给了这个按钮,所以我们按下这个按钮的时候就能在控制台看到输出的114514。

并且,我们通过在主类中写了一个windowClose的static方法,这样,我们通过方法的封装直接实现了点击关闭按钮关闭窗口的监听事件。

2、单监听器监听多个事件

如果我们想实现多个按钮同时监听一个事件呢?我们可以只写一个监听类,通过更改setActionCommand达到不同的监听效果。

如下图所示,我们点击start按钮可以在控制台输出“开始”

如果我们点击Stop按钮,会输出“哼哼”

这种效果其实就是一个监听器监听了多个事件

package top.woodwhale.study2;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TestActionEvent2 {
    public static void main(String[] args) {
        // 两个按钮,实现同一个监听
        // 开始按钮和停止按钮
        Frame frame = new Frame("Start ~ Stop");
        Button button = new Button("Start");
        Button button1 = new Button("Stop");

        // 可以显示的定义触发会返回的命令,如果不显示定义,则会走默认的值
        // 这样我们可以多个按钮,但是只需要一个监听类,只需要更改setActionCommand
        button1.setActionCommand("Stop");
        MyMonitor myMonitor = new MyMonitor();
        button.addActionListener(myMonitor);
        button1.addActionListener(myMonitor);

        frame.add(button,BorderLayout.NORTH);
        frame.add(button1,BorderLayout.SOUTH);

        frame.setSize(300,300);
        frame.以上是关于JavaGUI编程的主要内容,如果未能解决你的问题,请参考以下文章

贪吃蛇-JavaGUI实现

VSCode自定义代码片段——JS中的面向对象编程

结对编程之队友代码分析

VSCode自定义代码片段9——JS中的面向对象编程

第14篇-JAVA GUI编程

使用 Pygments 检测代码片段的编程语言