简介
GUI的核心技术:Swing、AWT
学习原因:了解MVC架构;了解监听
1.用AWT进行一些底层的实现
AWT包含了很多类和接口,包含的元素有:窗口、按钮、文本框等
1.1、组件和容器
1. Frame
package com.kuang.lesson01;
import java.awt.*;
//GUI的第一个界面
public class TestFrame {
public static void main(String[] args){
//Fram JDK,看源码!
Frame frame = new Frame("我的第一个java图形界面窗口");
//需要设置可见性
frame.setVisible(true);
//设置窗口大小
frame.setSize(400,400);
//设置窗口颜色
frame.setBackground(new Color(255, 47, 77));
//弹出的初始位置
frame.setLocation(200, 200);
//设置大小固定
frame.setResizable(false);
}
}
效果图:问题是发现窗口关闭不掉,解决办法是停止java的运行
效果图:
2. 面板Panel
解决了关闭事件!
package com.kuang.lesson01;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
//Panel 可以看成是一个空间,但是不能单独存在
public class TestPanel {
public static void main(String[] args) {
//Frame是一个总的窗口,我们所有的命令都在上面
Frame frame = new Frame();
//布局的概念
Panel panel = new Panel();
//设置布局
frame.setLayout(null);
//坐标
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(255,65,98));
//panel设置坐标,相对于frame
panel.setBounds(50,50,300,300);
panel.setBackground(new Color(65,85,79));
//往窗口上添加面板
frame.add(panel);
frame.setVisible(true);
//解决界面不能关闭的问题:监听事件,监听窗口关闭时间。用适配器模式
frame.addWindowListener(new WindowAdapter() {
//窗口点击关闭需要做的事情
@Override
public void windowClosing(WindowEvent e) {
//结束程序
System.exit(0);
}
});
}
}
效果图:
3.布局管理器
- 流式布局
package com.kuang.lesson01;
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()); //默认居中
frame.setLayout(new FlowLayout(FlowLayout.LEFT)); //靠左
frame.setSize(200,200);
//把按钮添加上去
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.setVisible(true);
}
}
- 东西南北中
package com.kuang.lesson01;
import java.awt.*;
public class TestBorderLayout {
public static void main(String[] args) {
Frame frame = new Frame("TestBorderLayout");
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(500, 500);
frame.setVisible(true);
}
}
效果图:
- 表格布局 Grid
package com.kuang.lesson01;
import java.awt.*;
public class TestGridLayout {
public static void main(String[] args) {
Frame frame = new Frame();
Button btn1 = new Button("btn1");
Button btn2 = new Button("btn2");
Button btn3 = new Button("btn2");
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);
frame.pack(); //java函数,会自动选择一个最优的按钮放置位置
frame.setVisible(true);
}
}
效果图:
2.1 事件监听
当某个事情发生的时候干什么
package com.kuang.lesson02;
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();
//因为,addActionListener(需要一个ActionListener,所以我们构造了一个ActionListener)
MyActionListener myActionListener = new MyActionListener();
button.addActionListener(myActionListener);
frame.add(button, BorderLayout.CENTER);
frame.pack();
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 e) {
System.out.println("aaa"); //运行完之后,点击按钮会产生输出“aaa”这样一个事件
}
}
package com.kuang.lesson02;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestActionTwo {
public static void main(String[] args) {
//两个按钮,实现同一个监听
//开始 停止
Frame frame = new Frame("开始-停止");
Button button1 = new Button("start");
Button button2 = new Button("stop");
button2.setActionCommand("button2-stop");
//new一个事件
MyMonitor myMonitor = new MyMonitor();
//让按钮获得事件
button1.addActionListener(myMonitor);
button2.addActionListener(myMonitor);
frame.add(button1, BorderLayout.NORTH);
frame.add(button2, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
}
class MyMonitor implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) { //e是获取到某些信息(按钮信息)
System.out.println("按钮被点击了:msg" + e.getActionCommand());
}
}
按钮被点击了:msg(点击start)
按钮被点击了:msgbutton2-stop(点击stop)
2.1.1 输入框事件监听
最终代码
package com.kuang.lesson02;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestText01 {
public static void main(String[] args) {
new MyFrame();
}
}
class MyFrame extends Frame{
public MyFrame() throws HeadlessException {
TextField textField = new TextField();
add(textField);
//监听输入的文本
MyListener myListener = new MyListener();
//按下回车,就会触发这个输入框的事件
textField.addActionListener(myListener);
//设置替换编码
textField.setEchoChar('*');
pack();
setVisible(true);
}
}
class MyListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
TextField field = (TextField)e.getSource(); //获得一些资源,返回一个对象(查看源代码知
//getSource是Object对象,所以向下转型,监听的是谁,就转成谁,这样我们就在监听器里面拿到了textField对象)
System.out.println(field.getText()); //就可以获得输入框中的文本
field.setText(""); //回车之后把文本变成空
}
}
替换编码效果图:
但在运行界面是真实的文本
2.1.2 简易计算器 组合加内部类复习
oop原则:组合 大于继承,不会产生较大的耦合性
class A extends B{ //继承
}
class A{ //A还是A,只是要把B组合进来
//怎么拥有B的功能呢?私有进来
public B b;
}
目前代码(面向过程)
package com.kuang.lesson02;
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() throws HeadlessException {
//3个文本框
TextField textField1 = new TextField(10);
TextField textField2 = new TextField(10);
TextField textField3 = new TextField(20);
//1个按钮
Button button = new Button("=");
button.addActionListener(new MyCalculator(textField1, textField2, textField3));
//1个标签
Label label = new Label("+");
//从左到右布局,流式布局
setLayout(new FlowLayout());
add(textField1);
add(label);
add(textField2);
add(button);
add(textField3);
pack();
setVisible(true);
}
}
class MyCalculator implements ActionListener{
//获取三个变量,采用有参构造器,在上面new MyCalculator的时候传参过来
private TextField num1, num2, num3;
public MyCalculator(TextField num1, TextField num2, TextField num3) {
this.num1 = num1;
this.num2 = num2;
this. num3 = num3;
}
@Override
public void actionPerformed(ActionEvent e) {
//1.获得加数和被加数
//num1.getText(); //为什么要num1. 是因为传过来的参数是一个对象,只有.了才能获取传过来的文本,
// 但是传过来的是String类型,需要转换成int类型
int n1 = Integer.parseInt(num1.getText()); // 使用Integer转换
int n2 = Integer.parseInt(num2.getText());
//2.将这个值+法运算后,放到第三个框
num3.setText(""+(n1+n2));
//3.清除前面两个框
num1.setText("");
num2.setText("");
}
}
优化代码:采用组合的方式(面向对象)
package com.kuang.lesson02;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestCalc {
public static void main(String[] args) {
new Calculator().loadFrame();
}
}
class Calculator extends Frame{
//属性
TextField num1, num2, num3;
//方法
public void loadFrame(){
//3个文本框
TextField textField1 = new TextField(10);
TextField textField2 = new TextField(10);
TextField textField3 = new TextField(20);
//1个按钮
Button button = new Button("=");
//1个标签
Label label = new Label("+");
button.addActionListener(new MyCalculator(this));
//从左到右布局,流式布局
setLayout(new FlowLayout());
add(textField1);
add(label);
add(textField2);
add(button);
add(textField3);
pack();
setVisible(true);
}
}
//监听器类
class MyCalculator implements ActionListener{
//获取计算器这个对象,在一个类中组合另一个类
Calculator calculator = null;
public MyCalculator(Calculator calculator) {
this.calculator = calculator;
}
@Override
public void actionPerformed(ActionEvent e) {
//1.获得加数和被加数
//num1.getText(); //为什么要num1. 是因为传过来的参数是一个对象,只有.了才能获取传过来的文本,
// 但是传过来的是String类型,需要转换成int类型
int n1 = Integer.parseInt(calculator.num1.getText());
int n2 = Integer.parseInt(calculator.num1.getText());
//2.将这个值+法运算后,放到第三个框
calculator.num3.setText(""+(n1+n2));
//3.清除前面两个框
calculator.num1.setText("");
calculator.num2.setText("");
}
}
优化代码:采用内部类(完全面向对象)
package com.kuang.lesson02;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestCalc {
public static void main(String[] args) {
new Calculator().loadFrame();
}
}
class Calculator extends Frame{
//属性
TextField num1, num2, num3;
//方法
public void loadFrame(){
//3个文本框
TextField textField1 = new TextField(10);
TextField textField2 = new TextField(10);
TextField textField3 = new TextField(20);
//1个按钮
Button button = new Button("=");
//1个标签
Label label = new Label("+");
button.addActionListener(new MyCalculator());
//从左到右布局,流式布局
setLayout(new FlowLayout());
add(textField1);
add(label);
add(textField2);
add(button);
add(textField3);
pack();
setVisible(true);
}
//监听器类
//内部类的最大好处就是可以畅通无阻的访问外部类的属性和方法
private class MyCalculator implements ActionListener{
//变成内部类之后就可以直接用自己的属性,不用单独new
// //获取计算器这个对象,在一个类中组合另一个类
// Calculator calculator = null;
//
// public MyCalculator(Calculator calculator) {
// this.calculator = calculator;
// }
@Override
public void actionPerformed(ActionEvent e) {
//1.获得加数和被加数
//num1.getText(); //为什么要num1. 是因为传过来的参数是一个对象,只有.了才能获取传过来的文本,
// 但是传过来的是String类型,需要转换成int类型
int n1 = Integer.parseInt(num1.getText());
int n2 = Integer.parseInt(num1.getText());
//2.将这个值+法运算后,放到第三个框
num3.setText(""+(n1+n2));
//3.清除前面两个框
num1.setText("");
num2.setText("");
}
}
}
2.1.3 画笔paint
2.1.4 鼠标监听
目的:实现鼠标画画
原理图:
package com.kuang.lesson03;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Iterator;
//鼠标监听事件
public class TestMouseListener {
public static void main(String[] args) {
new MyFrame("画图");
}
}
class MyFrame extends Frame {
//画画需要画笔,需要监听鼠标事件,需要集合来存储这些点
ArrayList points;
public MyFrame(String title) {
super(title);
//设置一个画板
setBounds(200,200,400,400);
//存鼠标的点
points = new ArrayList<>();
//鼠标监听器,针对于这个窗口的 this表示当前这个窗口
this.addMouseListener(new MyMouseListener());
setVisible(true);
}
//重写画笔(具体实施的类)
@Override
public void paint(Graphics g) {
//通过画笔画画,画下的每一个点都需要与鼠标绑定,所以需要监听鼠标的事件,添加一个鼠标的监听器
//把集合里面的点迭代出来
Iterator iterator = points.iterator();
while (iterator.hasNext()){
Point point = (Point) iterator.next(); //next指向了下一个后会返回一个当前的点
g.setColor(Color.BLUE);
g.fillOval(point.x, point.y,10,10);
}
}
//添加一个点到界面上,用paint()把点画上去 怎么把paints里面的点拿到并画上去呢?
//画到数组里面的类
public void addPaint(Point point){ //把监听器里面的点添加到画笔里面
points.add(point);
}
// private class MyMouseListener implements MouseListener{ // 如果直接这样写,需要重写MouseListener里面全部的方法
//
// }
//所以我们采用适配器模式写一个监听器(监听的类)
private class MyMouseListener extends MouseAdapter {
//鼠标 按下,弹起,按住不放
@Override
public void mousePressed(MouseEvent e) { //e获取鼠标资源
//e.getSource(); //要返回当前对象,我们是用MyFrame调用的,所以需要返回同样类型的对象 向下转型
MyFrame frame = (MyFrame) e.getSource(); //这样就拿到了窗口,拿到了之后我们就要画东西,点一下画一下
// 点击的时候会在界面产生一个点,所以从这把思路转化到画笔即paint
//产生一个点的坐标,鼠标的点怎么拿?e就代表当前的鼠标,e.getSource就代表调用它的,叫frame
Point point = new Point(e.getX(), e.getY());
frame.addPaint(point); //当前的点是传到了集合里面去遍历,points
//每次点击鼠标都需要重新画一遍,因为第一次执行画笔的时候,初始的集合里面并没有东西,所以画完就没了
frame.repaint();//刷新
}
}
}
//监听器里面的点,放到集合里面(通过addPaint()类),再通过画笔即paint类画出来
2.1.5 窗口监听
package com.kuang.lesson03;
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() {
setBackground(Color.BLACK);
setBounds(100,100,200,200);
setVisible(true);
//addWindowListener(new MyWindowsListener());
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
setVisible(false);
System.exit(0);
}
});
}
//换匿名内部类来写
// class MyWindowsListener extends WindowAdapter{
// @Override
// public void windowClosing(WindowEvent e) {
// setVisible(false); //隐藏窗口,通过按钮,隐藏当前窗口
// System.exit(0); //正常退出
// }
// }
}