5.1 Swing 类库
Java 的 Swing 类库 是根据 AWT 类库进行的二次封装,AWT 作为它的底层。Swing 类库更加的简单!更加的 人性化。具有很多 AWT 没有的 东西。
举个最简单的例子:AWT 只能画一些线,形状呀,文字呀。但是 Swing 能画图。 (剩下的就不说了,反正 Swing 就是比 AWT 牛逼的存在。)
格式:JFrame(继承了 Frame 所有的东西!并且比 Frame 多了很多东西,还优化了 Frame 很多Bug!)
5.1.1 JFrame 窗体 --> 面板架构
JFrame 窗体是根据 Frame 窗体改进过来的,它并不只拥有Frame一层面板,而且还具有 Root Pane、Layered Pane、Content Panne、Glasss Pane。
你是否听过 JFrame 的面板架构呢?很多 学习Java 的爱好者,只知道在使用 Swing 的 JFrame 时,必须先获取 ContentPane 然后在 Content Pane 上进行 添加组件和操作,但是他们并不知道原因是什么!
- 面板架构:
1.RootPane:
JFrame 窗体压根就没有去用 原生态的 Frame,而是在 Frame窗体的上面 建立了 RootPane!(相当于一个面板Panel 添加到了 Frame 窗体上。)这是为什么?答:这是因为 JFrame 拥有 工具条和菜单条,甚至还有玻璃面板。所以必须要拥有多个 面板来进行分层处理。而RootPane只作为 根面板(并提供相关的功能方法) 来支撑 其它 有真实作用的面板!
RootPane 与 Frame 类似于同级,当你 直接 用JFrame.add() 添加组件的时候,实际上 是添加到了 RootPane 面板上!
所以你可能会看到这两种形式:JFrame.getContentPane(); or JFrame.getRootPane().getContentPane(); 来获取其它面板。
RootPane 可以获取到 面板架构里 任何 面板!
- LayeredPane(并不是 JPanel 而是 JLayeredPane):
分层面板,不是普通的 JPanel 面板,而是只存在于 Swing 类库中的一个 新的 容器类型 “JLayeredPane”(这也显得 它在面板架构中承上启下的重要性)!是为了 定位 内容面板而存在的!内容面板就是根据它相对定位的。内容面板也是添加到分层面板上的!而分层面板是 根据 RootPane 相对定位的。并且 菜单条也是添加在分层面板上的。内容面板只不过是 LayeredPane 上一个 Z = -30000 的 JPanel 面板。
LayeredPane 具有 Z属性 层级,这将意味着 可以用 LayeredPane 面板做一些层级分明的事情,比如 哪个组件可以覆盖哪个组件 去显示。
注意:我们一般通过 add 的第二个参数来赋予 Z属性,如果没有赋予!那么它会和同样没有赋予Z属性的组件视为 同级!同级的组件,只在乎 添加的先后顺序!即谁最后 add 的,那么谁就 显示在上面。
- ContentPane:
JFrame 里最重要的 面板,内容面板。它是一个 可见的 容器,不包括 菜单条。它是 添加在 LayeredPane 面板上 Z = -30000 的 JPanel!(Z 相当于 CSS:z-index 的层级)我们一般 把想要添加的 组件 都添加在 ContentPane 面板上!
- GlassPane:
GlassPane 很奇特,它仅仅是一个面板,但却与 JLayeredPane 处于同级的位置!甚至 它显示的 层面是 JFrame 面板架构 的最高层!!!这是为什么呢?
答:是因为 GlassPane 可以 拦截事件!说白了就是,如果 JFrame 没有GlassPane 在最高层 帮忙 拦截事件 的话,无论你有什么监听器,都是监听不到的。因为 JFrame 是依靠 GlassPane 拦截事件的。
通常 GlassPane 是被隐藏起来的,如果想要 它显示出来!可以自己 将一个 JPanel 设定为 GlassPane 然后 setVisible(true),就能看到 它了。
5.1.2 Swing 类库 对 JFrame 的基本使用
- 创建JFrame 窗体
JFrame frame = new JFrame("这是一个JFrame 窗口");
frame.setBounds(100,100,200,200);
frame.setVisible(true);
- 获取 ContentPane 面板容器
Container contentPane = frame.getContentPane();
//Container contentPane =frame.getRootPane().getContentPane();
- 添加组件及调用方法
JLabel label = new JLabel("我是个标签");
contentPane.add(label);
contentPane.setBackground(Color.yellow);
- 添加事件
label.addMouseListener(new MouseAdapter() {
@Overridepublic void mousePressed(MouseEvent e) {
super.mousePressed(e);System.out.println("你点击标签干JB?");}
});
5.1.3 new 组件的位置or对齐设定 和 设置四种关闭方式
- new 组件的位置or对齐设定
当你 new 一个组件的时候,请仔细 观察它的参数,可能就有 位置的设定或对齐的设定!比如说 JLabel 的第二参数。就是 关于水平对齐方式的设定!
JLabel label = new JLabel("我是个标签",SwingConstants.CENTER);
lable.setHorizontalAlignment(SwingContants.CENTER); //极其难记的 水平对齐 方法。
SwingConstants.CENTER 是一个常量 0 (Constants 英文意思 常数,并不是 Content 别认错了,唉 ~)
意思是相对于 整个 内容面板 水平居中!
- 设置四种关闭方式
- DO_NOTHING_ON_CLOSE,(在你点击关闭按钮的时候,不会被关闭,)不执行任何操作。这个T喵 的 ~我现在都不知道 有啥用。
- HIDE_ON_CLOSE,(当你点击关闭按钮的时候,不会释放内存,只是隐藏该界面,没有真正的关闭,还占有资源)只隐藏界面,setVisible(false)。
- DISPOSE_ON_CLOSE,点击关闭按钮的时候,隐藏并释放窗体,dispose(),当最后一个窗口被释放后,则程序也随之运行结束。JVM 虚拟机里 可能有很多需要释放的窗口,DISPOSE_ON_CLOSE 就是 将当前这个窗口 隐藏,并且加入 到 被释放的队列里!等待着 被释放!!!才能实现真正的关闭。
- EXIT_ON_CLOSE,直接关闭应用程序,System.exit(0)。一个main函数对应一整个程序。这个是我们最常用的了,直接 退出程序了,还关闭 个 啥了。哈哈 ~
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setDefaultCloseOperation() 这个方法 难背吧 ??
- 代码展示
package com.muquanyu.lesson04;import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;public class JFrameDemo {
public static void main(String[] args) {
new JFrameDemo().init();}public void init(){
JFrame frame = new JFrame("这是一个JFrame 窗口");frame.setVisible(true);frame.setBounds(100,100,200,200);Container contentPane = frame.getContentPane();//Container contentPane =frame.getRootPane().getContentPane();//关闭事件frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);JLabel label = new JLabel("我是个标签",SwingConstants.CENTER);contentPane.add(label);contentPane.setBackground(Color.yellow);label.addMouseListener(new MouseAdapter() {
@Overridepublic void mousePressed(MouseEvent e) {
super.mousePressed(e);System.out.println("你点击标签干JB?");}});}
}