文章目录
1、awt简介
Abstract Window Toolkit
,抽象窗口工具集
- AWT中的图形函数与操作系统所提供的图形函数之间有着一一对应的关系,称之为peers,当利用AWT编写图形用户界面时,实际上是在利用本地操作系统所提供的图形库。
- 由于不同操作系统的图形库所提供的样式和功能是不一样的,在一个平台上存在的功能在另一个平台上则可能不存在。为了实现Java语言所宣称的“一次编写,到处运行(write once, run anywhere)”的概念,AWT不得不通过牺牲功能来实现平台无关性,也即AWT所提供的图形功能是各种操作系统所提供的图形功能的交集。
java.awt包主要类的层次关系
- 层次结构
在AWT中,所有能在屏幕上显示的组件(component)对应的类,均是抽象类Component的子类或子孙类。
这些类均可继承Component类的变量和方法。
Container类是Component的子类,它也是一个抽象类,它允许其他的组件(Component)加入其中。加入的Component也允许是Container类型,即允许多层嵌套的层次结构,Container类在将组件以合适的形式安排在屏幕上时很有用,它有两个子类,Panel和Window,它们不是抽象类。
- 独立
Window对应的类为java.awt.Windows, 它可独立于其他Container而存在,它有两个子类, Frame和Dialog, Frame是具有标题(title)和可伸缩的角(resize corner)的窗口(Window)。Dialog则没有菜单条,虽然它能移动,但不能伸缩。
滚动面板(ScrollPane)也是Window类的子类,这里就不讨论了。
Panel对应的类为java.awt.Panel,它可包含其他Container类型的组件,或包含在浏览器窗口中。Panel标识了一个矩形区域,该区域允许其他组件放入。Panel必须放在Window或其子类中才能显示。
2、awt
的基本使用
容器
容器(Container)也是一个类,实际上是Component的子类,因此容器本身也是一个组件,具有组件的所有性质,但是它的主要功能是容纳其它组件和容器。容器可以简化图形化界面的设计,以整体结构来布置界面。所有的容器都可以通过add()方法向容器中添加组件。
- 常用的容器3种:Panel, Frame, Applet。
- 框架(Frame)
构造方法
Frame frm = newFrame("New Window");
要生成一个窗口,通常使用Window的子类Frame类进行实例化,而不是直接使用Window 类,框架的外观就像平常Windows系统下的窗口,有标题、边框、菜单和大小等。setSize()方法可以设置框架尺寸的大小,setVisibe()方法可以设置窗口的可见性。
- 面板(Panel)
构造方法:
Panel pnl = new Panel();
面板是一种透明的容器,没有标题和边框。与Frame 不同,Panel不能作为最外层的容器单独存在,它首先必须作为一个组件放置在其他容器(一般为Frame)中,然后把组件添加到它里面。在java.swing中则是JPanel。
构造方法:
Applet apt = new Applet();
框架一般用作Java应用程序的窗口,而Applet是Java小程序的窗口。与Frame不同,Applet是在网页中显示的,也可以通过添加Panel进行组件布局。
3、关于窗口的几个函数
setSize(int width, int height);
定义控件的大小,它有两个参数,设置控件的宽度和高度。
setLocation(int x, int y);
将组件移到新位置,用x 和 y 参数来指定新位置的左上角坐标。
setBounds(int x,int y,int width,int,height);
可以看做上两个方法的组合,x,y定义位置,width,height定义宽度和高度。
public void dispose()
释放此窗口使用的所有原生屏幕资源、其子组件和所有所属子组件。也就是说,这些组件的资源将被销毁,它们消耗的任何内存都将返回到os,并且它们将被标记为不可显示。
public void pack()
设置窗口的最佳大小
public void repaint()
此方法会导致尽快调用此组件的更新方法。
4、基本布局
4.1 FlowLayout布局
import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class MyFlowLayout { public static void main(String []args){ // 声明一个类实例 MyFlowLayout mFlow = new MyFlowLayout(); // 创建一个外部容器, 容器名-->FlowLayout效果 Frame f = new Frame("FlowLayout效果"); Button button1, button2, button3; // 设置布局管理器 f.setLayout(new FlowLayout(FlowLayout.CENTER,100,200)); button1 = new Button("btn1"); button2 = new Button("btn2"); button3 = new Button("btn3"); f.add(button1); f.add(button2); f.add(button3); f.setSize(200,200); f.pack(); f.setVisible(true); // 添加Window监听器 // x 退出程序 f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent evt){ f.dispose(); System.exit(0); } }); } }
- 运行结果
坑:(后面学习持续更新)
为什么
f.pack()
去掉之后那些按钮不显示?
4.2 BorderLayout布局
import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class MyBorderLayout { private Frame f; private Button east, north,south, west; public static void main(String []args){ MyBorderLayout myB = new MyBorderLayout(); myB.go(); } public void go(){ f = new Frame("BorderLayout展示"); // 设置窗口的属性 f.setBounds(0,0,300,300); f.setLayout(new BorderLayout()); north = new Button("上"); south = new Button("下"); west = new Button("西"); east = new Button("东"); f.add(BorderLayout.NORTH, north); f.add(BorderLayout.SOUTH, south); f.add(BorderLayout.EAST, east); f.add(BorderLayout.WEST, west); f.setVisible(true); // 添加事件监听, 关闭框 f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent evt){ f.dispose(); System.exit(0); } }); } }
- 运行结果
- 坑:
为什么设置中文按钮就没办法正常显示,英文就可以?(不当人系列)
5、组件
5.1 Dialog 会话
import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class MyDialog { public static void main(String[] args) { Frame f = new Frame("Dialog Test"); f.setLayout(new FlowLayout()); f.setBounds(300,400,600,800); Dialog dlgModal = new Dialog(f, "Modal Dialog", true); // 打开该会话框之后,在当前会话框结束之前,不能在主对话框进行操作 Dialog dlgNonModal = new Dialog(f, "Non-modal Dialog", false); // 打开该会话框之后,依然可以在主对话框进行操作 Button btnModal = new Button("Modal"); Button btnNonModal = new Button("Non Modal"); dlgModal.setBounds(20, 30, 200, 300); dlgNonModal.setBounds(100, 200, 400, 500); btnModal.addActionListener(e -> dlgModal.setVisible(true)); btnNonModal.addActionListener(e -> dlgNonModal.setVisible(true)); f.add(btnModal,BorderLayout.NORTH); f.add(btnNonModal,BorderLayout.SOUTH); Button cbtn = new Button("close"); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent evt){ f.setVisible(false); System.exit(0); } }); dlgModal.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent evt){ dlgModal.dispose(); } }); cbtn.addActionListener(e->dlgNonModal.dispose()); dlgNonModal.add(cbtn); f.setVisible(true); } }
6、添加事件监听
6.1 什么是事件(源)
- 事件:
用户的每一个操作,如按下了一个按键,敲击了一下鼠标
- 事件源:
发出事件的组件
6.2 为什么要添加事件监听
对于事件源而言,需要有“事件监听器”对该事件源(即当前组件)进行监听,才能在事件源产生事件时及时通知响应的处理程序对事件进行处理。
所以监听器在这里充当着"观察者"的角色, 发现事件之后,通知程序作出响应的响应。
6.3 什么是监听器
监听器是一个实现了特定事件监听功能的类的实例对象。
6.4 什么是适配器
- 为什么要有适配器?
因为在实现监听器接口来编写一个监听器类的时候,接口所定义的所有抽象方法都需要被实现,即使对某个事件的方法并不感兴趣, 这就会造成大量的重复而意义不大的事。
为了解决这个问题才出现的适配器,提供了与监听器接口配套的适配器类。
- 适配器类就是监听器类里面的所有事件方法的空实现。
- 有什么好处?
引入适配器之后,在编写监听器类的时候,直接继承响应的适配器类,然后编写感兴趣的事件方法即可。
$It's good to get out of your comfort zone.