JavaGUI-01-AWT

简介

image-20220331135554625

AWT

AWT介绍

AWT:抽象的窗口工具

GUI:图形用户编程

image-20220331140640431 image-20220331140651063

1.组件和容器

窗口(Windows)

Frame

package AWT_Study;

import java.awt.*;

public class Frame_Test {
    public static void main(String[] args) {
        //Frame,JDK,看源码
        Frame frame = new Frame("我的第一个Java图形界面窗口");

        //设置窗口大小
        frame.setSize(400,400);

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

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

        //设置窗口大小固定(不可拉伸)
        frame.setResizable(false);
        
        //需要设置可见性
        frame.setVisible(true);
    }
}

image-20220331143805305

回顾封装

package AWT_Study;

import java.awt.*;

public class Frame_Test02 {
    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.cyan);
        MyFrame myFrame3 = new MyFrame(100, 300, 200, 200, Color.black);
        MyFrame myFrame4 = new MyFrame(300, 300, 200, 200, Color.GREEN);
    }
}

class MyFrame extends Frame {
    //全局变量,可能存在多个窗口,需要计数
    static int id = 0;

    //构造方法,参数:初始坐标(x,y),长宽,颜色
    public MyFrame(int x, int y, int w, int h, Color color) {
        //调用父类构造方法,Frame(String);
        //MyFrame1,MyFrame2...
        super("MyFrame" + (++id));

        //由于继承了Frame 可直接调用Frame的共有方法
        setBounds(x, y, w, h);
        setBackground(color);
        setVisible(true);
    }
}

image-20220331151111275

面板(Panel)

Panel放在Frame里面

package AWT_Study;

import java.awt.*;

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

        Frame frame = new Frame();

        Panel panel = new Panel();

        //设置布局(默认会把frame置顶)
        frame.setLayout(null);

        //设置frame
        frame.setBounds(300,300,500,500);
        frame.setBackground(new Color(204, 255, 124));

        //设置panel
        panel.setBounds(50,50,400,400);//设置坐标(相对于frame)
        panel.setBackground(new Color(238, 248, 211, 176));

        //给frame添加panel
        //add(Component),Panel继承自Container继承自Component
        frame.add(panel);

        frame.setVisible(true);
    }
}

image-20220331154142664

2.布局管理器

  • 流式布局-FlowLayout
package AWT_Study;

import java.awt.*;

public class FlowLayout_Test {

    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.CENTER));
        //frame.setLayout(new FlowLayout(FlowLayout.LEFT));
        frame.setLayout(new FlowLayout(FlowLayout.RIGHT));

        frame.setBounds(100,100,200,200);

        frame.add(button1);
        frame.add(button2);
        frame.add(button3);

        frame.setVisible(true);
    }

}

以FlowLayout.RIGHT为例

image-20220331163253697
  • 东西南北中-BorderLayout
package AWT_Study;

import java.awt.*;

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

        Button north = new Button("North");
        Button south = new Button("South");
        Button west = new Button("West");
        Button east = new Button("East");
        Button center = new Button("Center");

        frame.add(north,BorderLayout.NORTH);
        frame.add(south,BorderLayout.SOUTH);
        frame.add(west,BorderLayout.WEST);
        frame.add(east,BorderLayout.EAST);
        frame.add(center,BorderLayout.CENTER);

        frame.setSize(100,100);
        frame.setVisible(true);

    }
}

image-20220331164422405
  • 表格布局-GridLayout
package AWT_Study;

import java.awt.*;

public class GridLayout_Test {
    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");
        Button button4 = new Button("button4");
        Button button5 = new Button("button5");
        Button button6 = new Button("button6");

        frame.setLayout(new GridLayout(3,2));

        frame.add(button1);
        frame.add(button2);
        frame.add(button3);
        frame.add(button4);
        frame.add(button5);
        frame.add(button6);

        frame.setSize(100,100);

        frame.setVisible(true);
    }
}

image-20220331170341438

练习题

image-20220331171227758

我的答案

        //frame
        Frame frame = new Frame();
        frame.setBounds(200,200,500,300);
        frame.setBackground(Color.black);
        //设置为Grid布局 两行一列
        frame.setLayout(new GridLayout(2,1));
image-20220331180252610
        //填充frame
        Panel pUp = new Panel(new BorderLayout());
        pUp.setBackground(Color.blue);

        Panel pDown = new Panel(new BorderLayout());
        pDown.setBackground(Color.GRAY);

        frame.add(pUp);
        frame.add(pDown);
image-20220331180428060
        //填充pUp
        Button pUp_Button_west = new Button("west_Up");
        Button pUp_Button_east = new Button("east_Up");

        Panel pUp_Panel = new Panel(new GridLayout(2,1));
        Button pUp_Panel_Button1 = new Button("pUp_Panel_Button1");
        Button pUp_Panel_Button2 = new Button("pUp_Panel_Button2");
        pUp_Panel.add(pUp_Panel_Button1);
        pUp_Panel.add(pUp_Panel_Button2);


        pUp.add(pUp_Button_west,BorderLayout.WEST);
        pUp.add(pUp_Button_east,BorderLayout.EAST);
        pUp.add(pUp_Panel,BorderLayout.CENTER);
image-20220331182006099
        //填充pDown
        Button pDown_Button_west = new Button("west_Do");
        Button pDown_Button_east = new Button("east_Do");

        Panel pDown_Panel = new Panel(new GridLayout(2,2));
        Button pDown_Panel_Button1 = new Button("pDown_Panel_Button1");
        Button pDown_Panel_Button2 = new Button("pDown_Panel_Button2");
        Button pDown_Panel_Button3 = new Button("pDown_Panel_Button3");
        Button pDown_Panel_Button4 = new Button("pDown_Panel_Button4");
        pDown_Panel.add(pDown_Panel_Button1);
        pDown_Panel.add(pDown_Panel_Button2);
        pDown_Panel.add(pDown_Panel_Button3);
        pDown_Panel.add(pDown_Panel_Button4);

        pDown.add(pDown_Button_west,BorderLayout.WEST);
        pDown.add(pDown_Button_east,BorderLayout.EAST);
        pDown.add(pDown_Panel,BorderLayout.CENTER);
image-20220331183252897

更好的写法

        //frame(装p1,p2)
        Frame frame = new Frame();
        frame.setBounds(200,200,500,300);
        frame.setBackground(Color.black);
        //设置为Grid布局 两行一列
        frame.setLayout(new GridLayout(2,1));

        //四个面板(p1装p2 p3装p4)
        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));

        //上面
        p2.add(new Button("p2-Btn-1"));
        p2.add(new Button("p2-Btn-2"));

        p1.add(new Button("West-1"),BorderLayout.WEST);
        p1.add(new Button("Eest-1"),BorderLayout.EAST);
        p1.add(p2,BorderLayout.CENTER);

        //下面
        for (int i = 0; i < 4; i++) {
            p4.add(new Button("for-"+i));
        }

        p3.add(new Button("West-2"),BorderLayout.WEST);
        p3.add(new Button("Eest-2"),BorderLayout.EAST);
        p3.add(p4,BorderLayout.CENTER);


        frame.add(p1);
        frame.add(p3);

        frame.setVisible(true);

总结

image-20220331185903719

3.事件与监听

1.ActionEvent

image-20220401140230107

try1:一个Button的监听事件,点击按钮在控制台输出字符串

package AWT_Study;

import java.awt.*;
import java.awt.event.*;

public class ActionEvent_Test {
    public static void main(String[] args) {
        Frame frame = new Frame();
        frame.setSize(100,100);

        Button button = new Button("Hello! I’m Button");

        //因为addActionListener(ActionListener)需要一个ActionListener,所以要构造一个ActionListener
        MyActionListenner myActionListenner = new MyActionListenner();

        button.addActionListener(myActionListenner);

        frame.add(button,BorderLayout.CENTER);

        windowClose(frame);//关闭窗口

        frame.setVisible(true);
    }

    //关闭窗口的事件
    private static void windowClose(Frame frame){
        //addWindowListener(WindowListener)
        //我们需要在addWindowListener()中”填上“一个实现了WindowListener接口的“实现类”

        //抽象类WindowAdapter implements WindowListener接口
        /*
        WindowAdapter是抽象类不能“new”(不能实例化)
        我们需要在addWindowListener()的”括号里“
        写一个匿名内部类
        写出new出对象的具体的实现方法

        相当于new了一个继承自addWindowListener抽象类的”实现类“


        为什么不new一个继承自WindowListener接口的”实现类“呢?
        因为继承接口就需要实现接口的所有方法,而这里我们只需要windowClosing()方法
        所以选择继承抽象类addWindowListener,只需要重写windowClosing()方法就可以了

        */
        frame.addWindowListener(new WindowAdapter() {
            @Override
            //点击关闭时
            public void windowClosing(WindowEvent e) {
                //退出程序
                System.exit(0);
            }
        });
    }

}

//public interface ActionListener extends EventListener
//ActionListener extends EventListener接口,需要实现void actionPerformed(ActionEvent var1)方法
//IDEA快捷键:选中“ActionListener” alt+insert
//事件监听
class MyActionListenner implements ActionListener{
    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        System.out.println("我是一个Button!!!");
    }
}

补充:

1.extends和implements

(54条消息) java中extends和implements的区别_foreverhuylee的博客-CSDN博客

extends是继承类,implements是实现接口。
类只能继承一个,接口可以实现多个。
extends继承父类的时候可以重写父类的方法,也可以调用父类的非私有方法;implements实现接口,必须实现接口的所有方法

内部类和匿名内部类的用法

(54条消息) Java内部类和匿名内部类的用法_pan_jinquan的博客-CSDN博客_java匿名类和匿名内部类


try2:多个按钮共用一个事件(Listenner);

点击“start”按钮输出开始,点击“stop”按钮输出停止

package AWT_Study;

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

public class ActionEvent_Test02 {
    public static void main(String[] args) {
        Frame frame = new Frame("start-stop");
        frame.setSize(200,200);
        frame.setLayout(new GridLayout(2,1));

        Button buttonStart = new Button("Start");
        Button buttonStop = new Button("Stop");

        //可以显示的设置按钮被点击后getActionCommand()返回的命令,默认值为按钮的label
        ///buttonStart.setActionCommand("START!");

        MyMonitor myMonitor = new MyMonitor();

        buttonStart.addActionListener(myMonitor);
        buttonStop.addActionListener(myMonitor);

        frame.add(buttonStart);
        frame.add(buttonStop);

        frame.setVisible(true);
    }
}

class MyMonitor implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        if(actionEvent.getActionCommand().equals("Start")){
            System.out.println("开始");
        }
        if(actionEvent.getActionCommand().equals("Stop")){
            System.out.println("停止");
        }
    }
}

2.输入框事件监听

文本框输入,控制台输出

public class Text_Test01 {
    public static void main(String[] args) {
        TextFrame textFrame = new TextFrame();
    }
}

class TextFrame extends Frame{
    public TextFrame(){

        setSize(200,70);

        TextField textField = new TextField();
        add(textField);

        //监听文本框输入的文字
        TextListener textListener = new TextListener();
        //按下enter触发事件
        textField.addActionListener(textListener);

        setVisible(true);
    }
}

class TextListener implements ActionListener{
    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        //拿到触发该事件的文本框(一个特定的实例)
        //tF是个引用吧
        TextField tF = (TextField)actionEvent.getSource();//返回一个Object对象,把它强制转化为TextField
        System.out.println(tF.getText());
        //清屏
        tF.setText("");
    }
}

简易计算器,组合+内部类回顾复习

oop原则:组合优先于继承 (可减少耦合)

class B{
    ...
}

//继承
class A extends B{
    
}

//组合
class A{
    public B b;
}

//两种方式 A 都 可以用到 B 的功能

简易计算器,点击“=”后计算两数之和,同时清空输入框

1.面向过程实现(虽然用了类,但实际上是面向过程的思维)

(逻辑全部在计算器类的构造器中实现了,这是面向过程的写法)

public class calculator_Test {
    public static void main(String[] args) {
        calculator calculator = new calculator();
    }
}

//计算器类
class calculator extends Frame{
    public calculator(){
        //三个文本框
        TextField textF_A = new TextField(10);//可输入的最大长度
        TextField textF_B = new TextField(10);
        TextField textF_Sum = new TextField(20);

        //一个标签
        Label lableAdd = new Label("+");

        //一个按钮
        Button button = new Button("=");
        //事件传参
        button.addActionListener(new myCalculatorMonitor(textF_A, textF_B, textF_Sum));

        //设置布局
        setLayout(new FlowLayout());

        //add
        add(textF_A);
        add(lableAdd);
        add(textF_B);
        add(button);
        add(textF_Sum);

        //大小自适应
        pack();

        setVisible(true);
    }
}

//计算器监视器
class myCalculatorMonitor implements ActionListener{

    private TextField tFA, tFB, tFS;

    public myCalculatorMonitor(TextField textF_A, TextField textF_B, TextField textF_Sum) {
        this.tFA = textF_A;
        this.tFB = textF_B;
        this.tFS = textF_Sum;
    }

    //按下等号按钮后
    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        //1.从前两个输入框获得两个加数
        int a = Integer.parseInt(tFA.getText());//字符串转Int
        int b = Integer.parseInt(tFB.getText());
        //2.计算和,显示到第三个输入框
        tFS.setText(""+(a+b));//不加括号输出的是字符串“a+b”,而不是a+b值的字符串
        //3.清空前两个输入框
        tFA.setText("");
        tFB.setText("");
    }
}

优化一次后的代码(更标准的面向对象编程:用到组合类)

(监听器类组合了计算机类)

public class calculator_Test {
    public static void main(String[] args) {
        Calculator calculator1 = new Calculator();
        Calculator calculator2 = new Calculator();
        Calculator calculator3 = new Calculator();

        calculator1.loadFrame();
        calculator2.loadFrame();
        calculator3.loadFrame();
    }
}

//计算器类
class Calculator extends Frame{

    //属性(private只能在类内访问)
    public TextField textF_A;
    public TextField textF_B;
    public TextField textF_Sum;

    //方法
    public void loadFrame(){

        //实例化三个文本框属性
        textF_A = new TextField(10);//可输入的最大长度
        textF_B = new TextField(10);
        textF_Sum = new TextField(20);
        //实例化一个标签
        Label lableAdd = new Label("+");
        //实例化一个按钮
        Button button = new Button("=");


        //添加监视器(把自己作为参数传给监视器,当Button被按下后,监视器将拿到拥有这个Button的calculator实例)
        button.addActionListener(new myCalculatorMonitor(this));


        //设置布局
        setLayout(new FlowLayout());
        //add
        add(textF_A);
        add(lableAdd);
        add(textF_B);
        add(button);
        add(textF_Sum);


        //大小自适应
        pack();
        setVisible(true);
    }

}

//计算器监视器
class myCalculatorMonitor implements ActionListener{

    //属性(监视器类组合了计算机类,计算机类是在外部定义的)
    Calculator calculator_Has_Pressed_Button;

    //构造器
    public myCalculatorMonitor(Calculator calculator) {
        this.calculator_Has_Pressed_Button = calculator;
    }

    //按下等号按钮后的动作
    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        //1.从前两个输入框获得两个加数
        int a = Integer.parseInt(calculator_Has_Pressed_Button.textF_A.getText());//字符串转Int
        int b = Integer.parseInt(calculator_Has_Pressed_Button.textF_B.getText());
        //2.计算和,显示到第三个输入框
        calculator_Has_Pressed_Button.textF_Sum.setText(""+(a+b));//不加括号输出的是字符串“a+b”,而不是a+b值的字符串
        //3.清空前两个输入框
        calculator_Has_Pressed_Button.textF_A.setText("");
        calculator_Has_Pressed_Button.textF_B.setText("");
    }
}
image-20220402174340160

依次按下等号按钮

image-20220402174429144
完全改造为面向对象

上面代码中存在一个问题:有关计算的操作是在另一个类(myCalculatorMonitor)中完成的,我们希望可以直接在Calculator类中完成

使用内部类:实现更好的包装

内部类的最大好处:可以畅通无阻的访问外部的属性和方法!

具体操作:把监听器类作为计算器类的内部类(用面向对象的思维来看监听器是计算器的一个属性)

public class calculator_Test {
    public static void main(String[] args) {
        Calculator calculator1 = new Calculator();
        Calculator calculator2 = new Calculator();
        Calculator calculator3 = new Calculator();

        calculator1.loadFrame();
        calculator2.loadFrame();
        calculator3.loadFrame();
    }
}

//计算器类
class Calculator extends Frame{

    //属性(private只能在类内访问)
    public TextField textF_A;
    public TextField textF_B;
    public TextField textF_Sum;
    //监听器(是计算器类“内部”的类,在计算器类的内部定义)
    //内部类的最大好处:可以畅通无阻的访问外部的属性和方法!
    //myCalculatorMonitor可以直接使用Calculator的所有属性和方法
    private class myCalculatorMonitor implements ActionListener{
        //按下等号按钮后的动作
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            //1.从前两个输入框获得两个加数
            int a = Integer.parseInt(textF_A.getText());//字符串转Int
            int b = Integer.parseInt(textF_B.getText());
            //2.计算和,显示到第三个输入框
            textF_Sum.setText(""+(a+b));//不加括号输出的是字符串“a+b”,而不是a+b值的字符串
            //3.清空前两个输入框
            textF_A.setText("");
            textF_B.setText("");
        }
    }

    //方法
    public void loadFrame(){

        //实例化三个文本框属性
        textF_A = new TextField(10);//可输入的最大长度
        textF_B = new TextField(10);
        textF_Sum = new TextField(20);
        //实例化一个标签
        Label lableAdd = new Label("+");
        //实例化一个按钮
        Button button = new Button("=");

        //添加监视器
        button.addActionListener(new myCalculatorMonitor());

        //设置布局
        setLayout(new FlowLayout());
        //add
        add(textF_A);
        add(lableAdd);
        add(textF_B);
        add(button);
        add(textF_Sum);

        //大小自适应
        pack();
        setVisible(true);
    }
}
image-20220402181223270

3.画笔

public class Paint_Test {

    public static void main(String[] args) {
        new MyPaint().LoadFrame();
    }

}

class MyPaint extends Frame{

    public void LoadFrame(){
        setBounds(200,200,500,400);
        setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.blue);
        //椭圆(空心)
        g.drawOval(100,100,50,60);
        //椭圆(实心)
        g.fillOval(200,200,50,60);

        g.setColor(Color.BLACK);
        g.fillRect(150,150,50,50);
    }
}
image-20220402191902700

4.鼠标监听

目标:在鼠标点击的处画上一个点

image-20220403191833634
public class MouseListener_Test {
    public static void main(String[] args) {
        new MyFrame("画点").loadFrame();
    }
}

class MyFrame extends Frame{

    //属性
    //存鼠标点击的所有坐标
    private ArrayList points;

    public MyFrame(String title){
        //调用父类构造器
        super(title);
    }

    public void loadFrame(){
        setBounds(300,300,500,400);

        //实例化points
        points = new ArrayList<>();

        //为窗口添加鼠标监听器
        this.addMouseListener(new MyMouseMonitor());

        setVisible(true);
    }

    //画points中的所有点
    @Override
    public void paint(Graphics g) {
        g.setColor(Color.BLACK);
        //用迭代器遍历points,画出points中存储的所有点
        Iterator iterator = points.iterator();
        while(iterator.hasNext()){
            Point point = (Point) iterator.next();
            g.fillOval(point.x,point.y,10,10);
        }
    }

    //适配器模式
    //MouseAdapter是MouseListener接口的一个实现类
    //我们直接继承MouseAdapter,只需要重写MouseAdapter的部分方法即可
    //(如果implement MouseListener接口的话需要实现接口的所有方法)
    private class MyMouseMonitor extends MouseAdapter{
        @Override
        public void mousePressed(MouseEvent e) {
            //监听的对象是MyFrame所以返回的是MyFrame类型
            MyFrame frame = (MyFrame) e.getSource();
            //获得mousePressed事件发生时,鼠标的坐标点
            Point point = e.getPoint();
            //把这个点存储到points中
            frame.points.add(point);

            //重新绘制
            frame.repaint();//会调用paint方法(把所有的点重新画一遍)
        }
    }
}
image-20220403191441304

5.窗口监听

public class WindowListener_Test {
    public static void main(String[] args) {
        new WindowFrame().loadFrame();
    }
}

class WindowFrame extends Frame{

    public void loadFrame(){
        setBounds(200,200,300,200);
        //用到匿名内部类
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("窗口关闭中");
                System.exit(0);
            }

            @Override
            public void windowActivated(WindowEvent e) {
                WindowFrame windowFrame = (WindowFrame) e.getSource();
                windowFrame.setTitle("窗口已激活");
            }
        });
        setVisible(true);
    }
}

6.键盘监听

public class KeyListener_Test {
    public static void main(String[] args) {
        new KeyFrame().loadFrame();
    }
}

class KeyFrame extends Frame{
    public void loadFrame(){
        this.setBounds(200,200,100,100);
        this.setVisible(true);
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //获得当前按下的是哪个键 每个键对应一个code(int类型)
                int keyCode = e.getKeyCode();
                if(keyCode == KeyEvent.VK_A)
                    System.out.println("你按下了 A 键");
            }
        });
    }
}

posted @ 2022-03-31 19:05  Cornfield_Chase  阅读(75)  评论(0)    收藏  举报