- AWT(Abstract Window Toolkit),中文译为抽象窗口工具包,该包提供了一套与本地图形界面进行交互的接口,是Java提供的用来建立和设置Java的图形用户界面的基本工具。
- 常用组件:如下关系图
1.1、Frame
构造方法:
Frame frame = new Frame("New Window");
要生成一个窗口,通常使用Window的子类Frame类进行实例化,而不是直接使用Window 类,框架的外观就像平常Windows系统下的窗口,有标题、边框、菜单和大小等。
案例演示:
package awtdemo;
import java.awt.*;
import java.util.Set;
public class TestFrame {
public static void main(String[] args) {
//new一个窗口
Frame frame = new Frame("我的第一个界面");
//设置窗口的大小,这个传的参数只能是boolean类型,true为可变,false就是不可变
frame.setResizable(true);
//设置窗口的可见性,传的参数也只能是boolean类型
frame.setVisible(true);
//设置窗口的背景颜色,这里可以new一个Color类自己RGB颜色,也可以直接传一个Color
// frame.setBackground(new Color(85,150,86));
frame.setBackground(Color.BLACK);
//设置窗口的大小
frame.setSize(400,600);
//设置窗口的初始弹出来的位置
frame.setLocation(500,500);
}
}
效果展示:
然后发现关闭不了,那是因为我们没有设置关闭时间,现在只能通过IDEA停止java程序来关闭,如上图箭头所示。
1.2、Panel
构造方法:
Panel pnl = new Panel();
面板是一种透明的容器,没有标题和边框。与Frame 不同,Panel不能作为最外层的容器单独存在,它首先必须作为一个组件放置在其他容器(一般为Frame)中,然后把组件添加到它里面。在java.swing中则是JPanel。
案例演示:
package awtdemo;
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("我的第二个界面");
//new一个Panel
Panel panel = new Panel();
//设置流式布局
frame.setLayout(null);
//设置最外面窗口弹出的坐标位置和背景颜色
frame.setBounds(300,400,500,600);
frame.setBackground(Color.BLUE);
//设置透明画板的弹出位置和背景颜色
panel.setBounds(50,50,400,500);
panel.setBackground(Color.LIGHT_GRAY);
//把panel添加进Frame中
frame.add(panel);
//把最外层窗口可见性设置为可见,两个就都可见了
frame.setVisible(true);
//设置关闭事件 这个是适配器模式,后面再继续探究,现在先用着
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
效果展示:
问题:如果把Panel的坐标设置的没有在Frame 的坐标范围内会怎么样?
出来的效果窗口就只会显示Frame不会显示Panel,因为我第一遍测试的时候试了,只会出现Frame设置的效果,要想让Panel显示只能通过放大Frame去看到他,想去尝试的小伙伴可以去尝试一下。
1.3、布局管理器
1.3.1、流布局管理器(FlowLayout)
FlowLayout是Panel 和 Applet 的默认布局管理器。在该布局管理器中,组件在容器中按照从上到下,从左到右的顺序进行排列,行满后则换行。
构造方法较多,例如:
-
FlowLayout();
默认构造方法,设置居中对齐方式,横向和纵向间隔均为默认5像素
-
FlowLayout(FlowLayout.LEFT);
设置居左对齐,横向和纵向间隔均为默认5像素
-
FlowLayout(FlowLayout.RIGHT,20,40);
设置居右对齐,横向间隔20像素,纵向间隔40像
package awtdemo;
import java.awt.*;
public class TestLayout {
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.RIGHT,20,40));
//frame.setLayout(new FlowLayout(FlowLayout.TRAILING);
//frame.setLayout(new FlowLayout(FlowLayout.CENTER));
//frame.setLayout(new FlowLayout(FlowLayout.LEFT));
//frame.setLayout(new FlowLayout(FlowLayout.LEADING));
frame.setSize(600,200);
//把按钮添加到Frame面板中
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.setVisible(true);
}
}
效果展示:
1.3.2、边界布局管理器(BorderLayout)
构造方法:
BorderLayout bl = new BorderLayout();`
BorderLayout是Window、Frame和Dialog的默认布局管理器,其将容器分成North、South、East、West和Center 5个区域,每个区域只能放置一个组件。在使用add()方法添加组件到容器时,必须指定将其放置在哪个区域中。使用BorderLayout时,如果容器大小发生变换,组件的相对位置不变
案例演示:
package awtdemo;
import java.awt.*;
public class TestBorderLayout {
public static void main(String[] args) {
Frame frame = new Frame("我的第四个窗口");
//创建五个按钮
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(700,700);
frame.setVisible(true);
}
}
效果展示:
1.3.3、网格布局管理器(GridLayout)
构造方法:
GridLayout gl = new GridLayout(3,5); //3行5列
GridLayout 可使容器中的各个组件呈网格状布局,平局占据容器的空间,即使容器的大小发生变化,每个组件还是平均占据容器的空间。和FlowLayout一样,GridLayout也是按照从上到下,从左到右的规律进行排列的。
案例演示:
package awtdemo;
import java.awt.*;
public class TestGridLayout {
public static void main(String[] args) {
Frame frame = new Frame("我的第五个窗口");
frame.setSize(400,500);
Button button1 = new Button("1");
Button button2 = new Button("1");
Button button3 = new Button("1");
Button button4 = new Button("1");
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.add(button4);
//设置为两行两列
frame.setLayout(new GridLayout(2,2));
frame.setVisible(true);
}
}
效果展示:
练习:如何让按钮按照如下图所示布局
过程分析➕案例演示:
package awtdemo;
import java.awt.*;
/*
1.首先我们需要一个顶级的窗口Frame
2.把这个顶级Frame分割成上下两部分,我们就会想到Panel(特性:无法单独显示,必须添加到某个容器中)
3.再把上下两个再分割成两个部分(左右中这个结构),我们我们就需要四个Panel
4.把4个Panel用边界布局管理器排列好完成Panel和Panel之间的嵌套
5.把嵌套好的Panel添加大奥Frame中即可
*/
public class PractiseDemo {
public static void main(String[] args) {
//顶级窗口
Frame frame = new Frame("我的第六个窗口");
frame.setSize(500,400);
frame.setLocation(500,500);
frame.setBackground(Color.BLACK);
frame.setVisible(true);
frame.setLayout(new GridLayout(2,1));
//4个面板
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));
//第一部分
//给面板1增添两个按钮并用边界布局管理器布局到左右两侧
p1.add(new Button("p1-button"),BorderLayout.WEST);
p1.add(new Button("p1-button"),BorderLayout.EAST);
//给面板2增添两个按钮
p2.add(new Button("p2-button"));
p2.add(new Button("p2-button"));
//把2面板用边界布局管理器添加到1面板的中间
p1.add(p2,BorderLayout.CENTER);
//第二部分
//给面板3增添两个按钮并用边界布局管理器布局到左右两侧(跟面板1的操作相同)
p3.add(new Button("p3-button"),BorderLayout.EAST);
p3.add(new Button("p3-button"),BorderLayout.WEST);
//中间四个我们可以用for循环去添加按钮,也可以手动一个个添加都行 这里用for循环
for (int i = 0; i < 4; i++) {
p4.add(new Button("p4-button"));
}
//把4面板用边界布局管理器添加到3面板的中间
p3.add(p4,BorderLayout.CENTER);
//因为上面我们已经把面板2和面板4添加到面板1和面板3上,所以我们只需要要把面板1和面板3添加到顶级窗口上即可显示
frame.add(p1);
frame.add(p3);
}
}
效果展示:
1.4、事件监听
上面我们实现了在面板上面绘制按钮,但是有了按钮,我们如何让按钮按下去有他的功能,这就需要我们给他设置。Button源代码调中用接口方法,而我们的监听处理函数则必须要实现该接口(ActionListener),这样利用多态,使得Button虽调用的为该接口的方法,但运行的则是我们new出来的对象方法。类似于Button提供了这么一个钩子,但是钩子上面是什么东西他自己并不清楚,我们只需要人为地往上面挂上我们需要的东西即可
案例演示:
package awtdemo;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/*
事假监听的四步:
1.要有时间的源对象:button
2.要发生某种事件(类):TestActionEvent,封装了事件的信息
3.要有监听器(接口):myActionlistener 接到事件后进行处理
4.要把监听器注册到事件源对象上 button.addActionListener(myActionlistener);
*/
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.setVisible(true);
//关闭窗口事件
windowClose(frame);
}
//关闭窗体的事件 适配器模式
private static void windowClose(Frame frame){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
//构造一个 ActionListener我们要继承 ActionListener这个接口,继承接口我们就要重写它里面的方法
class MyActionlistener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("我爱你");
}
}
效果展示:
案例演示:多个按钮,共享一个事件
package awtdemo;
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("我的第八个窗口");
Button button1 = new Button("start");
Button button2 = new Button("stop");
//setActionCommand()可以显示的定义出发回返回的命令,不如果不显示定义,会显示默认的值(即按钮的名字)
//可以多个按钮只写一个监听类
button2.setActionCommand("button-stop");
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.getActionCommand()接收定义的命令,并返回
System.out.println("按钮被点击了:"+e.getActionCommand());
}
}
效果展示:
1.5、输出框TextField监听
package awtdemo;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestText1 {
public static void main(String[] args) {
new MyFrame();//启动面板
}
}
class MyFrame extends Frame{
public MyFrame(){
TextField textField = new TextField();
add(textField);//把文本框加入面板
//监听这个文本框输入的文字
MyActionlistener2 myActionlistener2 = new MyActionlistener2();
//按下enter 就会触发这个输入框的事件
textField.addActionListener(myActionlistener2);
//设置替换编码
textField.setEchoChar('*');
setVisible(true);
pack();
}
}
//监听类
class MyActionlistener2 implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
TextField field = (TextField) e.getSource(); //获得一些资源,返回的一个对象
System.out.println(field.getText()); //获得输入框的文本
field.setText(""); //清除文本框 ""=null
}
}
效果展示:
1.6、简易加法计算器
package awtdemo;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestCalc {
public static void main(String[] args) {
new Calclator();
}
}
class Calclator extends Frame{
public Calclator(){
//1.三个文本框
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,num2,num3;
//创建三个变量的有参构造
public MycalculatorListener(TextField num1, TextField num2, TextField num3) {
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
}
@Override
public void actionPerformed(ActionEvent e) {
//1.获得加数和被加数
//因为getText()方法里面传的是String类型这里我们把它包装成int类型
int n1 = Integer.parseInt(num1.getText());
int n2 = Integer.parseInt(num2.getText());
//2.将这个值加法运算后,放到第三个框
num3.setText((n1+n2)+"");//自动装箱成String类型
//3.清除前两个框
num1.setText("");
num2.setText("");
}
}
效果展示:
改进:采用面向对象写法
package awtdemo;
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(){
num1 = new TextField(10);//字符数
num2 = new TextField(10);//字符数
num3 = new TextField(20);//字符数
Button button = new Button("=");
Label label = new Label("+");
button.addActionListener(new MyCalculatorListener(this));
//布局
setLayout(new FlowLayout());
add(num1);
add(label);
add(num2);
add(button);
add(num3);
pack();
setVisible(true);
}
}
//监听器类
class MyCalculatorListener implements ActionListener{
//获取计算器这个对象,在一个类中组合另外一个类;
Calculator calculator = null;
public MyCalculatorListener(Calculator calculator) {
this.calculator = calculator;
}
@Override
public void actionPerformed(ActionEvent e) {
//1. 获得加数和被加数
//2. 将这个值 + 法运算后,放到第三个框
//3. 清除前两个框
int n1 = Integer.parseInt(calculator.num1.getText());
int n2 = Integer.parseInt(calculator.num2.getText());
calculator.num3.setText(""+(n1+n2));
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() {
num1 = new TextField(10);//字符数
num2 = new TextField(10);//字符数
num3 = new TextField(20);//字符数
Button button = new Button("=");
Label label = new Label("+");
button.addActionListener(new MyCalculatorListener());
//布局
setLayout(new FlowLayout());
add(num1);
add(label);
add(num2);
add(button);
add(num3);
pack();
setVisible(true);
}
//监听器类
//内部类的好处,就是可以畅通无阻的访问外部的属性和方法!
private class MyCalculatorListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//1. 获得加数和被加数
//2. 将这个值 + 法运算后,放到第三个框
//3. 清除前两个框
int n1 = Integer.parseInt(num1.getText());//直接调用外部类的属性
int n2 = Integer.parseInt(num2.getText());
num3.setText("" + (n1 + n2));
num1.setText("");
num2.setText("");
}
}
}
1.7、画笔
案例演示:测试
package awtdemo;
import java.awt.*;
public class TextPaint {
public static void main(String[] args) {
new MyPaint().loadFrame();
}
}
class MyPaint extends Frame{
public void loadFrame(){
setBounds(300,300,500,600);
setVisible(true);
}
@Override
public void paint(Graphics g) {
//创建画笔的颜色
g.setColor(Color.red);
g.drawOval(200,100,100,100);
g.fillRect(100,100,100,100);
g.fillOval(200,200,200,200);
}
}
效果展示:
上述只是电脑在画画,怎么实现鼠标画画,这就需要鼠标监听实现鼠标画画
1.8、鼠标监听实现鼠标画画
原理图:
案例演示:
package awtdemo;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
//鼠标监听事件
public class TestMouseListener {
public static void main(String[] args) {
new MyFrame2("画图");
}
}
//画板的类
class MyFrame2 extends Frame{
//画画需要画笔。需要监听鼠标当前的位置,需要集合来存储
ArrayList points;
public MyFrame2(String title){
super(title);
setBounds(200,200,400,300);
points = new ArrayList<>();
setVisible(true);
//添加鼠标监听事件
this.addMouseListener(new MyMouseListener());
}
//重写画笔的方法
@Override
public void paint(Graphics g) {
Iterator iterator = points.iterator();
while (iterator.hasNext()){
Point point = (Point)iterator.next();
g.setColor(Color.black);
g.fillOval(point.x,point.y,10,10);
}
}
//添加一个点到界面上
public void addPaint(Point point){
points.add(point);
}
//鼠标监听事件(适配器模式)
private class MyMouseListener extends MouseAdapter{
//重写鼠标按压的方法
@Override
public void mousePressed(MouseEvent e) {
MyFrame2 frame2 = (MyFrame2)e.getSource();
//我们点击的时候,就会在界面上产生一个点,这个点就是我们鼠标的点
frame2.addPaint(new Point(e.getX(),e.getY()));
//每次点击鼠标都需要重新画一遍
frame2.repaint();//刷新
}
}
}
效果展示:
1.9、键盘监听
案例演示:
package awtdemo;
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.blue);
setBounds(100,100,200,200);
setVisible(true);
this.addWindowListener(
//匿名内部类
//适配器模式
new WindowAdapter() {
//关闭窗口
@Override
public void windowClosing(WindowEvent e) {
System.out.println("windowClosing");
//退出
System.exit(0);
}
//激活窗口
@Override
public void windowActivated(WindowEvent e) {
WindowFrame source = (WindowFrame) e.getSource();
source.setTitle("被激活了");
System.out.println("windowActivated");
}
}
);
}
}
1.10、键盘监听
package awtdemo;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class TestKetListener {
public static void main(String[] args) {
new KeyFrame();
}
}
class KeyFrame extends Frame{
public KeyFrame(){
setBounds(100,200,300,400);
setVisible(true);
//匿名内部类
this.addKeyListener(new KeyAdapter() {
//键盘按下
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
//打印的是每个键所对应的编码
System.out.println(keyCode);
//可以根据按下的不同的操作,产生不同的结果
if (keyCode == KeyEvent.VK_UP){
System.out.println("你按下了上键");
}
}
});
}
}
效果展示: