[Java进阶] Swing两万字大总结

2024-02-15  本文已影响0人  阿杰_96c5

⓵ 前言

和早期版本中的 AWT 相比,Swing 更为强大、性能更优良,它除了保留了 AWT 中几个重量级组件之外,其他组件都为轻量级组件。这样。使用 Swing 开发出的窗体风格会与当前运行平台上的窗体风格一致。同时,程序员也可以在跨平台时指定窗体统一的风格与外观。

⓶ 概述

GUI(图形用户界面)为程序提供图形界面,它最初的设计目的是为程序员构建一个通用的 GUI,使其能够在所有的平台上运行,但 Java 1.0 中基础类 AWT(抽象窗口工具箱)并没有达到这个要求,于是 Swing 出现了,它是 AWT 组件的增强组件,但是它又不能完全替代 AWT 组件,这两种组件需要同时出现在一个图形用户界面中。

🐱 Swing的特点

原来的 AWT 组件来自 java.awt 包,当含有 AWT 组件的 Java 应用程序在不同的平台上执行时,每个平台的 GUI 组件的显示会有所不同,但是在不同平台运行使用 Swing 开发的应用程序时,就可以统一 GUI 组件的显示风格,因为 Swing组件允许编程人员在跨平台时指定统一的外观和风格。

Swing 组件通常被称为 “轻量级组件”,因为它完全由 Java 语言编写,Java 是不依赖于操作系统的语言,它可以在任何平台上运行,而依赖于本地平台的组件相应地被称为 “重量级组件”,比如 AWT 组件就是依赖本地平台的窗口系统来决定组件的功能、外观和风格的。

Swing 主要具有以下特点。
(1) 轻量级组件
(2) 可插入外观组件

🐱 Swing包

为了有效地使用 Swing 组件,必须了解 Swing 包的层次结构和继承关系,其中比较重要的类是 Component 类、Container 类和 JComponent 类。下图描述了这些类的层次和继承关系。

Swing 组件中的大多数 GUI 组件都是 Component 类的直接子类或间接子类,JComponent 类是 Swing 组件各种特性的存放位置,这些组件的特性包括设定组件边界、GUI 组件自动滚动等。

Swing 组件中的最重要的父类是 Container 类,Container 类又有两个最重要的子类,分别为 java.awt.Windowjava.awt.Frame。除了以往的 AWT 类组件会继承这两个类之外,现在的 Swing 组件同样也会扩展了这两个类。

从上图中我们可以看到,顶层父类是 Component 类与 Container 类,所以 Java 关于窗口组件的编写,都与组件及容器的概念相关联。

🐱 常用组件概述

下面给出基本的 Swing 组件的概述,表中列举了常用的 Swing 组件及其含义。

组件名称 定义
JButton 按钮,按钮可以带一些图片或文字
JCheckBox 复选框
JComBox 下拉列表框,可以在下拉显示区域显示多个选项
JFrame 框架类
JDialog 对话框
JLabel 标签组件
JRadioButton 单选按钮
JList 能够在用户界面中显示一系列条目的组件
JTextField 文本框
JPasswordField 密码框
JTextArea 文本区域
JOptionPane 一些面板

⓷ 常见顶层窗体

窗体作为 Swing 应用程序中组件的承载体,处于非常重要的位置。Swing 中常用的窗体包括 JFrameJDialog 窗体,下面我们将会讲解这两个窗体的使用方法。

🐱JFrame窗体

JFrame 窗体是一个容器,它是 Swing 程序中各个组件的载体,因此,可以将 JFrame 看作是承载这些 Swing 组件的容器。

在开发应用程序时,可以通过继承 java.swing.JFrame 类来创建一个窗体,然后再在窗体中添加组件,同时为组件设置事件。由于该窗体继承了 JFrame 类,所以它拥有最大化、最小化和关闭按钮。

下面将详细讲解 JFrame 窗体在 Java 应用程序中的使用方法。

JFrame 在程序中的语法格式如下:

JFrame frame = new JFrame(title);
Container container = frame.getContentPane();

frameJFrame 类的对象。
containerContainer 类的对象,可以使用 JFrame 对象调用 getContentPane() 方法获取。

我们应该有这样的一个概念,就是 Swing 组件的窗体通常与组件和容器相关,所以在 JFrame 对象创建完成后,需要调用 getContentPane() 方法将窗体转换为容器,然后在容器中添加组件或设置布局管理器。通常这个容器用来包含和显示组件。如果需要将组件添加至容器,那么可以使用来自 Container 类的 add() 方法进行设置,示例代码如下:

container.add(new JButton("按钮"));                     //JButton按钮组件

在容器中添加组件后,也可以使用 Container 类的 remove() 方法将这些组件从容器中删除,示例代码如下:

container.remove(new JButton("按钮"));

我们来看看下面这个实例,该实例使用 JFrame 对象创建了一个窗体,然后在其中添加一个组件。

在项目中创建 MyFrame 类,该类继承 JFrame 类成为窗体类,然后在该类中创建标签组件,并添加到窗体界面中。

import java.awt.*;
import javax.swing.*;

public class MyFrame extends JFrame {                           //定义一个类继承JFrame类

    public void CreateJFrame(String title) {                    //定义一个CreateJFrame()方法

        JFrame frame = new JFrame(title);                        //实例化一个JFrame对象
        Container container = frame.getContentPane();           // 获取一个容器
        container.setBackground(Color.CYAN);                    //设置容器的背景颜色

        JLabel jl = new JLabel("这是一个JFrame窗体");         //创建一个JLabel标签
        jl.setHorizontalAlignment(SwingConstants.CENTER);       //使标签上的文字居中
        container.add(jl);                                      // 将标签添加到容器中

        frame.setVisible(true);                                //使窗体可视
        frame.setBounds(400,300,400, 300);                     //设置窗体显示位置和大小
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);         //设置窗体关闭方式
    }

    public static void main(String args[]) {
        //在主方法中调用createJFrame()方法
        new MyFrame().CreateJFrame("一个JFrame窗体");
    }
}

运行本实例程序,结果如下所示:


image.png

上述程序中的 MyFrame 类继承了 JFrame 类,在 CreateJFrame() 方法中实例子化 JFrame 对象。JFrame 类的常用构造方法包括下面两种形式。

public JFrame()

public JFrame(String title)

JFrame 类中的两种构造方法分别为无参的构造方法与有参的构造方法:

第一种形式的构造方法创建一个初始不可见、没有标题的新窗体。

第二种形式的构造方法在实例化该 JFrame 对象时,创建一个不可见但具有标题的窗体。

我们可以使用 JFrame 对象调用 show() 方法使窗体可见,但是这个方法早已被新版 JDK 弃用,现在通常使用 setVisible(true) 方法使窗体可见。

同时,可以使用 setBounds(x,y,width, height) 方法设置窗体显示位置和大小,其中 xy 为窗体左上角坐标,widthheight 为窗体的宽和高。

创建窗体后,需要给予窗体一个关闭方式,可以调用 setDefaultCloseOperation() 方法关闭窗体。

Java为关闭窗体提供了多种方式,常用的有4种方式,分别为:DO_NOTHING_ON_CLOSEDISPOSE_ON_CLOSEHIDE_ON_CLOSEEXIT_ON_CLOSE,这几种操作实质上是将一个 int 类型的常量封装在 javax.swing.WindowConstants 接口中。

具体含义如下:

关闭窗体方式 描述
EXIT_ON_CLOSE 退出应用程序,默认窗口关闭
DO_NOTHING_ON_CLOSE 什么都不做就将窗体关闭
DISPOSE_ON_CLOSE 移除窗口的默认窗口关闭操作
HIDE_ON_CLOSE 隐藏窗口的默认窗口关闭

🐱 JDialog 窗体

JDialog 窗体是 Swing 组件中的对话框,它继承了 AWT 组件中的 java.awt.Dialog 类。

JDialog 窗体的功能是从一个窗体中弹出另一个窗体,就像是在使用浏览器时弹出其他的对话框一样。JDialog 窗体实质上就是另一种类型的窗体,它与 JFrame 窗体类似,在使用 JDialog 窗体时也需要调用 getContentPane() 方法,从而将窗体转换为容器,然后在容器中设置窗体的特性。

在应用程序中创建 JDialog 窗体需要实例化 JDialog 类,通常使用以下几种 JDialog 类的构造方法。

构造方法 描述
public JDialog() 创建一个没有标题和父窗体的对话框
public JDialog(Frame f) 创建一个指定父窗体的对话框,但该窗体没有标题
public JDialog(Frame f, boolean model) 创建一个指定类型的对话框,并指定父窗体,但该窗体没有指定标题
public JDialog(Frame f, String title) 创建一个指定标题和父窗体的对话框
public JDialog(Frame f, String title, boolean model) 创建一个指定标题、窗体和模式的对话框

下面我们来看一个实例,该实例主要实现单击 JFrame 窗体中的按钮后弹出另一个对话框窗体的功能。

要求:在项目中创建 MyJDialog 类,该类继承 JDialog 窗体,然后在窗体中添加一个按钮,当用户单击该按钮后,程序将弹出一个对话框窗体。

import javax.swing.*;
import java.awt.*;

class MyJDialog extends JDialog {                           //创建新类继承JDialog类

    public MyJDialog(MyFrame frame) {
        //实例化一个JDialog类对象,指定对话框的父窗体、窗体标题和类型
        super(frame, "JDialog窗体", true);

        Container container = getContentPane();                    //创建一个容器
        container.add(new JLabel("这是一个对话框"));           //在容器中添加标签
        setBounds(120, 120, 150, 100);          //设置对话框窗体大小
    }
}

public class MyFrame extends JFrame {                            //创建新类

    public MyFrame() {
        Container container = getContentPane();                 //创建一个容器
        container.setLayout(null);

        JLabel label = new JLabel("这是一个JFrame窗体");      //在窗体中设置标签
        label.setHorizontalAlignment(SwingConstants.CENTER);    //将标签的文字置于标签中间位置
        container.add(label);

        JButton button = new JButton("点我弹出对话框");         //定义一个按钮
        button.setBounds(10, 10, 150, 20);

        //为按钮添加鼠标单击事件
        button.addActionListener(e -> {
            //使MyJDialog窗体可见
            new MyJDialog(MyFrame.this).setVisible(true);
        });

        container.add(button);                             // 将按钮添加到容器中
        container.setBackground(Color.white);

        setSize(400,300);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        // 实例化MyJDialog类对象
        new MyFrame();
    }
}

运行本实例,运行结果如下图所示:


image.png

本实例为了使对话框在父窗体中弹出,定义了一个 JFrame 窗体,然后在该窗体中添加一个按钮,并为此按钮添加一个鼠标单击监听事件(这儿使用了 lambda 表达式),这里使用 “new MyJDialog().setVisible(true)” 语句使对话框窗体可见,这样就实现了当用户单击该按钮后将弹出对话框的功能。

由于 MyJDialog 类继承了 JDialog 类,所以可以在构造方法中使用 super 关键字调用 JDialog 构造方法。这里使用了 “public JDialog(Frame f, String title, boolean model)” 这种形式的构造方法,同时设置了自定义的 JFrame 窗体及对话框的标题和窗体类型。

从本实例的代码可以看出,JDialog 窗体与 JFrame 窗体形式基本相同,甚至在设置窗体的特性时所调用的方法名称都基本相同,比如设置窗体大小、设置窗体关闭状态等。

⓸ 应用基本组件

软件界面是软件和用户之间的交流平台,而组件则是构成软件界面的基本元素,是软件和用户之间的交流途径。例如,用标签组件来显示相关信息,用单选按钮、复选框、文本框等接受用户的输入信息,用按钮来提交用户的输入信息等等。

🐱 标签组件:JLabel

JLabel 组件显示文本和图像时,不仅可以只显示其中的一者,而且可以同时显示。在通过构造方法创建组件对象时,可以设置标签内容相对于组件的水平显示位置。

JLabel 类提供的所有构造方法如下表所示:

构造方法 描述
JLabel() 创建一个既无文本内容,又无图像内容的标签
JLabel(String text) 创建一个具有文本内容的标签
JLabel(String text, int horizontalAlignment) 创建一个具有文本内容并且指定水平显示位置的标签
JLabel(Icon icon) 创建一个具有图像内容的标签
JLabel(Icon icon, int horizontalAlignment) 创建一个具有图像内容并且指定水平显示位置的标签
JLabel(String text, Icon icon, int horizontalAlignment) 创建一个既有文本内容,又有图像内容,并且指定水平显示位置的标签

构造方法中的入口参数 horizontalAlignment 可以从 JLabel 类的静态常量中选择,可选的静态常量如下表所示:

静态变量 常量值 标签内容显示位置
LEFT 2 靠左侧显示
CENTER 0 居中显示
RIGHT 4 靠右侧显示

JLabel 类中提供了众多的方法,方便程序员设置标签的内容,常用方法有以下几个:

方法 描述
setText(String text) 设置要显示的文本
setIcon(Icon icon) 设置要显示的图像
setHorizontalAlignment(int alignment) 设置标签内容在水平方向的对齐方式
setHorizontalTextPosition(int textPosition) 设置文本相对于图像在水平方向的位置
setVerticalAlignment(int alignment) 设置标签内容在垂直方向的对齐方式
setVerticalTextPosition(int textPosition) 设置文本相对于图像在垂直方向的位置
setIconTextGap(int iconTextGap) 设置文本和图像之间的距离,单位为像素,默认为 4 像素
setEnabled(boolean enabled) 设置标签是否可用,设为 false 时表示不可用,默认为可用
setDisabledIcon(Icon disabledIcon) 设置当标签不可以时显示的图像

下面我们将通过一个例子来进一步了解 JLabel 组件的使用方法。

要求:首先将窗口标题修改为 “添加标签”,然后创建一个带有指定文本的标签对象,并为标签添加一幅图像,设置标签内容的显示位置,最后将标签设置为不可用,并设置标签在不可用的情况下显示另一幅图像。

import javax.swing.*;

public class MyFrame extends JFrame {       //创建新类
    JLabel label;

    public MyFrame() {
        //修改窗口标题
        setTitle("添加标签");

        label = new JLabel("我是一个JLabel!", JLabel.CENTER);                               //创建指定文本的标签对象

        label.setIcon(new ImageIcon("C:\\Users\\15269\\Desktop\\自行车.png"));              //为标签添加图像

        label.setHorizontalTextPosition(JLabel.CENTER);                                    //设置文本相对于图像的水平位置

        label.setVerticalTextPosition(JLabel.BOTTOM);                                     //设置文本相对于图像的垂直位置

        label.setEnabled(false);                                                          //设置标签为不可用

        label.setDisabledIcon(new ImageIcon("C:\\Users\\15269\\Desktop\\射箭.png"));      //设置标签在不可用的情况下显示的图像

        add(label);  // 将标签添加到窗口中

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400,300,800,650);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new MyFrame();
    }
}

直接运行该实例,将会显示如下图所示的窗口:


image.png

在标签不可用的情况下文字是灰色的,如果未设置标签在不可用的情况下显示其他图像,那么显示的原图像也将是灰色的,比如我们将 label.setDisabledIcon(new ImageIcon(“C:\Users\15269\Desktop\射箭.png”)) 这一行注释掉,将会得到下图这样的图像:

image.png

如果我们将 label.setEnabled(false) 注释掉,将会得到这样的结果:

image.png

🐱 按钮组件

Swing 中的按钮是较为常见的组件,它用于触发特定动作。Swing 提供了很多种按钮,包括提交按钮、复选框按钮、单选按钮等,这些按钮都是从 AbstractButton 类中继承而来的。

🐶 普通按钮:JButton

Swing 中的普通按钮由 JButton 对象表示,其构造方法主要有如下几种形式:
① public JButton()
② public JButton(String text)
③ public JButton(Icon icon)
④ public JButton(String text, Icon icon)

通过使用上述构造方法,在 Swing 按钮上不仅能显示文本标签,还可以显示图标。上述构造方法中的第一个构造方法可以生成不带任何文字和图标的组件,然后根据需要再使用相应的方法为按钮设置指定的文本和图标,其他构造方法都在初始化时指定了按钮上显示的图标或文字。

下面我们通过一个简单的例子来进一步了解 JButton 的使用。

创建窗体,然后在窗体中添加两个按钮组件,分别用于显示文本内容与图片内容。

import javax.imageio.ImageIO;
import javax.swing.*;
import java.io.*;

public class MyFrame extends JFrame {       //创建新类
    JPanel root;
    JButton messageButton,imageButton;

    public MyFrame() throws IOException {
        root = new JPanel();      //定义面板容器
        setContentPane(root);
        setLayout(null);         //设置面板为绝对布局

        //按钮添加文字
        messageButton = new JButton("普通按钮");        //定义显示文本内容的按钮
        messageButton.setBounds(54, 68, 100, 40);      //设置按钮显示位置和大小
        root.add(messageButton);                       //将按钮添加到面板容器中

        //按钮添加图标
        ImageIcon icon = new ImageIcon(ImageIO.read(new File("C:\\Users\\15269\\Desktop\\坏笑.png")));                                             //定义图片对象
        imageButton = new JButton(icon);                //定义显示图片的按钮对象
        imageButton.setBounds(196, 40, 120, 120);       //定义按钮显示位置
        root.add(imageButton);                          //就按钮显示在面板中

        //设置窗口风格
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(400,300,400,300);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) throws IOException {
        new MyFrame();
    }
}

运行本程序,结果如下图所示:


image.png

🐶 单选按钮:JRadioButton

默认情况下的单选按钮显示为一个圆形图标,在该图标旁通常放置一些说明性文字。为了使多个单选按钮表现出某种功能,应用程序一般将多个单选按钮放置在按钮组中,即当用户选中某个单选按钮后,按钮组 中其他按钮将被自动取消选中。

单选按钮是 Swing 组件中 JRadioButton 类的对象,该类是 JToggleButton 的子类,而 JToggleButton 类又是 AbstractButton 类的子类,因此,单选按钮的一系列控制方法都是 AbstractButton 类中的方法。

(1) 单选按钮
可以使用 JRadioButton 类中的构造方法创建单选按钮对象。

JRadioButton 类的常用构造方法主要有以下几种形式:
① public JRadioButton()
② public JRadioButton(Icon icon)
③ public JRadioButton(Icon icon, boolean selected)
④ public JRadioButton(String text)
⑤ public JRadioButton(String text, Icon icon)
⑥ public JRadioButton(String text, Icon icon, boolean selected)

通过观察上述构造方法的形式,我们知道在初始化单选按钮时可以同时设置单选按钮的图标、文字及默认是否被选中等属性。

(2) 按钮组
Swing 存在一个 ButtonGroup 类,该类用于产生按钮组。如果希望将所有的单选按钮放置在按钮组中,那么我们需要实例化一个 JRadioButton 对象,并使用该对象调用 add() 方法添加单选按钮。

下面我们让通过一个简单的例子来看一下,创建窗体,然后在窗体中添加单选按钮。

import javax.swing.*;

public class MyFrame extends JFrame {       
    JPanel root;
    JRadioButton radioButton, radioButton_1, radioButton_2, radioButton_3;

    public MyFrame() {
        root = new JPanel();      //定义面板容器
        setContentPane(root);
        setLayout(null);         //设置面板为绝对布局

        //定义单选按钮
        radioButton = new JRadioButton("学习");
        radioButton_1 = new JRadioButton("打豆豆");
        radioButton_2 = new JRadioButton("运动");
        radioButton_3 = new JRadioButton("旅行");

        //定义按钮显示位置和大小
        radioButton.setBounds(45, 29, 73, 23);
        radioButton_1.setBounds(134, 29, 121, 23);
        radioButton_2.setBounds(45, 74, 73, 23);
        radioButton_3.setBounds(134, 74, 121, 23);

        //将按钮添加到面板中
        root.add(radioButton);
        root.add(radioButton_1);
        root.add(radioButton_2);
        root.add(radioButton_3);

        //定义按钮组控件
        ButtonGroup group = new ButtonGroup();

        //将单选按钮添加到按钮组中
        group.add(radioButton);
        group.add(radioButton_1);
        group.add(radioButton_2);
        group.add(radioButton_3);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 271, 161);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new MyFrame();
    }
}

本实例运行结果如下图所示:


image.png

从上面的代码可以看出,单选按钮与按钮组的用法基本类似,只是按钮组在实例化单选按钮对象后还需要将其添加到按钮组中。

🐶 复选框:JCheckBox

Swing 组件中的复选框的使用也非常广泛,一般情况下,它显示为一个方块图标,外加一段描述性文字。与单选按钮不同的是复选框可以进行多选选择,每一个复选框都提供 “选中” 与 “不选中” 两种状态。复选框由 JCheckBox 类的对象表示,它同样继承于 AbstractButton 类,所以复选框组件的属性设置也来源于 AbstractButton 类。

JCheckBox 的常用构造方法如下:
① public JCheckBox()
② public JCheckBox(Icon icon, Boolean checked)
③ public JCheckBox(String text, Boolean checked)

复选框与其他按钮的设置基本相同,除了可以在初始化时设置图标之外,还可以设置复选框的文字域是否被选中。

下面让我们来看一个实例,将滚动面板与复选框结合使用。
要求:在项目中创建 CheckBoxFrame 类,该类继承 JFrame 类成为窗体组件,在类中设置窗体添加多个复选框。

import javax.swing.*;

public class CheckBoxFrame extends JFrame {
    JPanel root;
    JCheckBox checkBox,checkBox_1,checkBox_2,checkBox_3;

    public CheckBoxFrame() {
        root = new JPanel();      //定义面板容器
        setContentPane(root);
        setLayout(null);         //设置面板为绝对布局

        //定义复选框组件
        checkBox = new JCheckBox("C");
        checkBox_1 = new JCheckBox("C++");
        checkBox_2 = new JCheckBox("Java");
        checkBox_3 = new JCheckBox("Python");

        //设置复选框显示位置和大小
        checkBox.setBounds(31, 28, 73, 23);
        checkBox_1.setBounds(132, 28, 73, 23);
        checkBox_2.setBounds(31, 75, 54, 23);
        checkBox_3.setBounds(132, 75, 74, 23);

        //往面板中添加复选框
        root.add(checkBox);
        root.add(checkBox_1);
        root.add(checkBox_2);
        root.add(checkBox_3);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 271, 161);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new CheckBoxFrame();
    }
}

运行本实例,运行结果如下图所示:


image.png

🐱 文本组件

在现实项目开发中,文本组件是使用最为广泛的组件,尤其是文本框与密码框组件,通过文本组件可以很轻松地处理单行文字、多行文字、口令字段。下面我们来看文本组件的定义及其使用。

🐶 文本框:JTextField

文本框用来显示或编辑一个单行文本,通过 Swing 中的 JTextField 类对象创建,该类继承了 javax.swing.text.JTextComponent 类。

下面列举了一些常用的创建文本框的构造方法。
① public JTextField()
② public JTextField(String text)
③ public JTextField(int fieldwidth)
④ public JTextField(String text, int fieldwidth)
⑤ public JTextField(Document docModel, String text, int fieldWidth)

从上面的构造方法中,我们可以看出,定义 JTextField 组件很简单,并且可以在初始化文本框时设置文本框的默认文字、文本框的长度等。

下面让我们来看一个关于文本框的实例。
要求:在项目中创建 JTextFieldFrame 类,该类继承 JFrame 类成为窗体组件,然后向该窗体添加标签组件和文本框组件。

import javax.swing.*;

public class JTextFieldFrame extends JFrame {
    JPanel root;
    JLabel userNameLabel,passWordLabel;
    JTextField userTextField,passWordTextField;
    JButton enterButton,closeButton;

    public JTextFieldFrame() {
        root = new JPanel();      //定义面板容器
        setContentPane(root);
        setLayout(null);         //设置面板为绝对布局

        //用户名标签
        userNameLabel = new JLabel("用户名:");
        userNameLabel.setBounds(52, 33, 54, 15);
        root.add(userNameLabel);

        //用户名文本框
        userTextField = new JTextField(12);
        userTextField.setBounds(116, 30, 139, 21);
        root.add(userTextField);

        //密码标签
        passWordLabel = new JLabel("密 码:");       //定义标签对象
        passWordLabel.setBounds(52, 74, 54, 15);
        root.add(passWordLabel);

        //密码文本框
        passWordTextField = new JTextField(12);
        passWordTextField.setBounds(116, 71, 139, 21);
        root.add(passWordTextField);

        //登录按钮
        enterButton = new JButton("登录");          //定义按钮对象
        enterButton.setBounds(64, 116, 69, 23);
        root.add(enterButton);

        //退出按钮
        closeButton = new JButton("退出");
        closeButton.setBounds(174, 116, 69, 23);
        root.add(closeButton);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 340, 256);
        setVisible(true);
    }

    //main方法
    public static void main(String[] args) {
        new JTextFieldFrame();
    }
}

该实例运行结果如下图所示:


image.png

🐶 密码框:JPasswordField

密码框与文本框的定义和用法基本相同,它们俩的区别是密码框使用户输入的字符串以某种符号进行加密。密码框对象是通过 JPasswordField 类 来 创 建 的,JPasswordField 类的构造方法与 JTextField 类的构造方法非常相似,下面列举几个常用的构造方法:
① public JPasswordField()
② public JPasswordFiled(String text)
③ public JPasswordField(int fieldwidth)
④ public JPasswordField(String text, int fieldwidth)
⑤ public JPasswordField(Document docModel, String text, int fieldWidth)

在程序中定义密码框,示例代码如下。

JPasswordField jp = new JPasswordField();
jp.setEchoChar('#');       //设置回显字符

使用 JPasswordField 类中所提供的 setEchoChar() 方法,可以改变密码框的回显字符。

下面我们运用密码框对前面的登录界面进行改进,代码如下:

import javax.swing.*;

public class JTextFieldFrame extends JFrame {
    JPanel root;
    JLabel userNameLabel,passWordLabel;
    JTextField userTextField;
    JButton enterButton,closeButton;
    JPasswordField passWordTextField;

    public JTextFieldFrame() {
        root = new JPanel();      //定义面板容器
        setContentPane(root);
        setLayout(null);         //设置面板为绝对布局

        //用户名标签
        userNameLabel = new JLabel("用户名:");
        userNameLabel.setBounds(52, 33, 54, 15);
        root.add(userNameLabel);

        //用户名文本框
        userTextField = new JTextField(12);
        userTextField.setBounds(116, 30, 139, 21);
        root.add(userTextField);

        //密码标签
        passWordLabel = new JLabel("密 码:");       //定义标签对象
        passWordLabel.setBounds(52, 74, 54, 15);
        root.add(passWordLabel);

        //密码文本框
        passWordTextField = new JPasswordField(12);
        passWordTextField.setBounds(116, 71, 139, 21);
        passWordTextField.setEchoChar('●');       //设置回显字符
        root.add(passWordTextField);

        //登录按钮
        enterButton = new JButton("登录");          //定义按钮对象
        enterButton.setBounds(64, 116, 69, 23);
        root.add(enterButton);

        //退出按钮
        closeButton = new JButton("退出");
        closeButton.setBounds(174, 116, 69, 23);
        root.add(closeButton);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 340, 256);
        setVisible(true);
    }

    //main方法
    public static void main(String[] args) {
        new JTextFieldFrame();
    }
}

改进后的运行结果如下:


image.png

🐶 文本域:JTextArea

文本域组件是一个非常常见而又十分重要的组件,用来接受用户的多行文字输入,它的使用也非常简单。

Swing 中的任何一个文本域都是 JTextArea 类型的对象,JTextArea 常用的构造方法如下:
① public JTextArea()
② public JTextArea(String text)
③ public JTextArea(int rows, int columns)
④ public JTextArea(Document doc)
⑤ public JTextArea(Document doc, String Text, int rows, int columns)

通过上述构造方法,我们可以在初始化文本域时提供默认文本、设置文本域的长与宽。

下面让我们通过一个实例来更好地理解和使用文本域。
要求:在项目中创建 JTextAreaFrame 类,该类继承 JFrame 类成为窗体组件,然后向该窗体中添加文本域组件。

import javax.swing.*;

public class JTextAreaFrame extends JFrame {
    JPanel root;
    JTextArea textArea;

    public JTextAreaFrame(String title) {
        super(title);

        root = new JPanel();      //定义面板容器
        setContentPane(root);
        setLayout(null);         //设置面板为绝对布局

        textArea = new JTextArea();              //定义文本域组件
        textArea.setLineWrap(true);              //设置文本域自动换行
        textArea.setBounds(20, 10, 290, 200);
        root.add(textArea);                      //将文本域添加到面板

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 340, 260);
        setVisible(true);
    }

    //main方法
    public static void main(String[] args) {
        new JTextAreaFrame("JTextArea");
    }
}

该实例运行结果如下:


image.png

JTextArea 类的 setLineWrap() 方法可以设置文本域的自动换行属性。文本域对象的初始状态是不允许换行的,调用该方法并给定参数 true,就可以将文本域设置为自动换行状态啦。

🐱 列表组件

Swing 提供了两种列表组件,分别为下拉列表框与列表框。

下拉列表框与列表框都是带有多个选项的组件,用户可以从中选择需要的选项。和下拉列表框相比,列表框显得更直观一些,它将所有选项罗列在列表框中,而下拉列表框显得更为便捷和美观,它将所有的项目隐藏起来,当用户需要选用其中的选项时才会显现出来。

🐶 下拉列表框:JComboBox

(1) JComoBox类
初次使用 Swing 中的下拉列表框时,会感觉到 Java 中的下拉列表框与 Windows 操作系统中的下拉列表框类似,但是实质上两者并不相同,Swing 中的下拉列表框不仅支持用户从中选择选项,同时还支持用户编辑项目中的内容。

下拉列表框是一个带条状的显示区,它具有下拉功能。在下拉列表框的右边存在一个倒三角形的按钮,当用户单击该按钮时,下拉列表框中的选项将会以列表的形式显示出来。

Swing 中的下拉列表框使用 JComboBox 类对象来表示,它是 javax.swing.JComponent 类的子类。

JComboBox 的常用构造方法如下。
① public JComboBox()
② public JComboBox(ComboBoxMode dataModel)
③ public JComboBox(Object[] arrayData)
④ public JComboBox(Vector vector)

在初始化下拉列表框时,既可以选择同时指定下拉列表框中的选项内容,也可以在程序中使用其他方法设置下拉列表框中的内容。下拉列表框中的内容可以被封装在 ComboBoxModel 类型、数组或者 Vector 类型中。

(2) JCcomboBox 模型
在开发程序时,一般将下拉列表框中的选项封装在 ComboBoxModel 类型中。ComboBoxModel 类型为接口,它代表一般模型,可以自定义一个类实现该接口,然后在初始化 JComboBox 对象时向上转型为 ComboBoxModel 接口类型,但是必须实现下面的两个方法:

① public void setSelectedItem(Object item)
② public Object getSelectedItem()

其中,setSelectedItem() 方法是设置下拉列表框的选中项,getSelectedItem() 方法用于返回下拉列表框中的选中项,有了这两个方法,我们就可以轻松地对下拉列表框中的项目进行操作。

自定义的这个类除了可以实现该接口外,还可以继承 AbstractListModel 类,在该类中也有两个操作下拉列表框的重要方法:

① getSize():返回列表的长度。
② getElementAt(in index):返回指定索引处的值。

下面让我们通过一个实例来更好地理解和使用下拉列表框。
要求:在项目中创建 JListDemoFrame 类,该类继承 JFrame 类成为窗体组件,然后向该窗体中添加下拉列表框组件。

import javax.swing.*;

public class JComboBoxFrame extends JFrame {
    JPanel root;
    JLabel messageLabel;
    JComboBox comboBox;

    public JComboBoxFrame(String title) {
        super(title);

        root = new JPanel();      //定义面板容器
        setContentPane(root);
        setLayout(null);         //设置面板为绝对布局

        messageLabel = new JLabel("请选择你的星座:");             //定义标签组件
        messageLabel.setBounds(31, 25, 130, 15);    //设置标签组件大小
        root.add(messageLabel);

        //定义字符串数组对象
        String[] constellations = {
                "白羊座", "金牛座", "双子座", "巨蟹座",
                "狮子座", "处女座", "天秤座", "天蝎座",
                "射手座", "摩羯座", "双鱼座", "水瓶座"
        };
        comboBox = new JComboBox(constellations);                    //定义下拉列表框组件
        comboBox.setBounds(130, 22, 100, 21);     //设置列表大小
        root.add(comboBox);                                         //将下拉列表添加到面板

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 310, 230);
        setVisible(true);
    }

    //main方法
    public static void main(String[] args) {
        new JComboBoxFrame("JComboBox");
    }
}

该实例运行结果如下:


image.png

🐶 列表框:JList

与下拉列表框相比,列表框将所有选项显示在列表框中,在窗体上占据固定的大小,如果列表框中的选项较多,需要具有滚动效果,那么可以将列表框放入滚动面板中。用户在选择列表框中的某一项后,按住 Shift 键并选择列表框中的其他选项,其他选项也会被选中。用户也可以按住 Ctrl 键并单击列表框中的项目,这样,列表框中的项目就处于非选中状态。

Swing 使用 JList 类对象来表示列表框,下面列举几个常用的构造方法:

① public void JList()
② public void JList(Object[] listData)
③ public void JList(Vector listData)
④ public void JList(ListMode dataModel)

在上述构造方法中,存在一个没有参数的构造方法,当使用该方法进行构造时,用户既可以在初始化列表框后使用 setListData() 方法对列表框进行设置,也可以在初始化的过程中对列表框中的选项进行设置。设置的方式有三种,分别为数组、Vector 类型和 ListModel 模型。

当使用数组作为构造方法的参数时,首先需要创建列表选项的数组,然后再利用构造方法来初始化列表框。

使用数组作为初始化列表框的参数,示例代码如下:

String[] contents={"列表1","列表2","列表3","列表4"};
JList jl = new JList(contents);

如果使用上述构造方法中的第三种构造方法,那么通常将 Vector 类型的数据作为初始化 JList 组件的参数,示例代码如下:

Vector contents = new Vector();
JList jl = new JList(contents);
contents.add("列表1");
contents.add("列表2");
contents.add("列表3");
contents.add("列表4");

如果使用 ListModel 模型为参数,那么需要创建 ListModel 对象。ListModelSwing 包中的一个接口,它提供了获取列表框属性的方法。但是在通常情况下,为了使用户不完全实现 ListModel 接口中的方法,通常自定义一个类继承实现该接口的抽象类 AbstractListModel。该类提供了 getElementAt()getSize() 方法,其中,getElementAt() 方法代表根据项目的索引获取列表框中的值,而 getSize() 方法用于获取列表框中项目的个数。

4 种构造方法我们具体来看一个实例。
要求:在项目中创建 Jlist 类,使该类继承 JFrame 类成为窗体组件,然后在该类中创建列表框,并添加到窗体中。

import javax.swing.*;

public class JListFrame extends JFrame {
    JPanel root;
    JList list;
    JScrollPane js;

    public JListFrame(String title) {
        super(title);

        root = new JPanel();      //定义面板容器
        setContentPane(root);
        setLayout(null);         //设置面板为绝对布局

        list = new JList(new MyListModel());
        js = new JScrollPane(list);
        js.setBounds(10, 10, 100, 100);
        root.add(js);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 260, 230);
        setVisible(true);
    }

    class MyListModel extends AbstractListModel {   //继承抽象类AbstractListModel
        private String[] constellations = {
                "白羊座", "金牛座", "双子座", "巨蟹座",
                "狮子座", "处女座", "天秤座", "天蝎座",
                "射手座", "摩羯座", "双鱼座", "水瓶座"
        };

        //设置列表框内容
        public Object getElementAt(int x) {    //重写getElementAt()方法
            if (x < constellations.length)
                return constellations[x++];
            else
                return null;
        }

        public int getSize() {                //重写getSize()方法
            return constellations.length;
        }
    }

    //main方法
    public static void main(String[] args) {
        new JListFrame("JList");
    }
}

运行该实例,运行结果如下图所示:


image.png

除了可以使用这个实例中所示的方式创建列表框之外,还可以使用 DefaultListModel 类创建列表框,该类扩展了 AbstractListModel 类,所以也可以通过 DefaultListModel 对象向上转型为 ListModel 接口初始化列表框。同时,DefaultListModel 类提供 addElement() 方法实现将内容添加到列表框中。

下面我们将使用 DefaultListModel 类来创建列表框,具体代码如下:

import javax.swing.*;

public class JListFrame extends JFrame {
    JPanel root;
    JList list;
    DataModel mode;

    public JListFrame(String title) {
        super(title);

        root = new JPanel();      //定义面板容器
        setContentPane(root);

        mode = new DataModel();

        list = new JList(mode);

        list.setBorder(BorderFactory.createTitledBorder("配件"));

        root.add(new JScrollPane(list));

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 260, 230);
        setVisible(true);
    }

    class DataModel extends DefaultListModel {

        String[] s = {"主板", "显示器", "内存", "CPU", "硬盘", "电源", "键盘", "鼠标", "显卡"};

        public int getSize() {
            return s.length;
        }

        public String getElementAt(int index) {
            return (index + 1) + "." + s[index++];
        }
    }

    //main方法
    public static void main(String[] args) {
        new JListFrame("JList");
    }
}

运行该实例,结果如下图所示:


image.png

🐱 向窗体中添加容器

窗体作为容器,单独使用时是没有意义的,需要向窗体中添加各种组件,从而实现其功能。面板也是一个 Swing 容器,因此可以容纳其他组件。面板不能像窗体一样单独使用,必须添加到其他容器中才能发挥作用。接下来我们来看一下 Swing 中的几种常用面板控件。

🐶 普通面板:JPanel

JPanel 面板继承自 java.awt.Container 类,它可以聚集一些组件进行布局。因此,它除了可以添加组件之外,也可以设置布局管理器,为面板中的组件布局。

下面让我们通过一个实例来看看 JPanel 的应用。
要求:在项目中创建 JPanelFrame 类,该类继承 JFrame 类成为窗体组件,然后在该类中创建 4Jpanel 面板组件,并将他们添加到窗体中。

import javax.swing.*;
import java.awt.*;

public class JPanelFrame extends JFrame {
    JPanel p1,p2,p3,p4;

    public JPanelFrame(String title) {
        super(title);

        //将整个容器设置为两行两列的网格布局
        setLayout(new GridLayout(2,2,2,2));

        //初始化面板,设置边界布局
        p1 = new JPanel(new BorderLayout());
        p2 = new JPanel(new BorderLayout());
        p3 = new JPanel(new BorderLayout());
        p4 = new JPanel(new BorderLayout());

        //在各面板中添加按钮
        p1.add(new JButton("p1"));
        p2.add(new JButton("p2"));
        p3.add(new JButton("p3"));
        p4.add(new JButton("p4"));

        //在容器中添加面板
        add(p1);
        add(p2);
        add(p3);
        add(p4);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 260, 260);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new JPanelFrame("JPanel");
    }
}

运行该实例,结果如下:


image.png

🐶 滚动面板:JScrollPane

在设置界面时,可能会遇到在一个较小的容器窗体中显示一段较多内容的情况,这时可以使用 JScrollPane 面板。

JScrollPane 面板是带滚动条的面板,也是一种容器,它只能放置一个组件,并且不可以使用布局管理器。如果需要在 JScrollPane 面板中放置多个组件,我们可以将多个组件放置在 JPanel 面板上,然后将 JPanel 面板作为一个整体组件添加在 JScrollPane 组件上。

下面让我们通过一个实例来了解 JScrollPane 的应用。
要求:在项目中创建 JScrollPaneFrame 类,该类继承 JFrame 类成为窗体组件,然后在类中创建 JScrollPane 滚动面板组件,该滚动面板组件包含 JTextArea 文本域组件。

import javax.swing.*;
import java.awt.*;

public class JScrollPaneFrame extends JFrame {
    JPanel root;
    JTextArea textArea;
    JScrollPane scrollPane;

    public JScrollPaneFrame(String title) {
        super(title);

        //创建文本域
        textArea = new JTextArea(30, 50);

        //创建JScrollPane面板对象
        scrollPane = new JScrollPane(textArea);

        //将该面板添加到容器中
        add(scrollPane);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 360, 300);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new JScrollPaneFrame("JScrollPane");
    }
}

运行该实例,结果如下:


image.png

🐶 分割面板:JSplitPane

分割面板可以将所在的区域分割成两部分,分开的部分之间有一分隔条,用户可以根据需要调整分隔条的位置来改变这两部分的相对大小,并且分割条两侧的每一部分中还可以再放入分割面板,实现分割面板的嵌套使用。

此外,分割面板还可以实现水平方向上的分割或者垂直方向上的分割,这样用户就可以根据需要选择是在水平方向上进行分割,还是在垂直方向上进行分割。

分割面板不像 JPanelJScrollPane 面板使用起来那么简单,因为使用分割面板时,需要设置分割面板是水平方向分割还是垂直方向分割等属性。

① 创建分割面板
我们使用 javax.swing.JSplitPane 类来创建一个分割面板对象。该类的常用方法如下表所示:

构造方法 功能
JSplitPane() 创建一个在水平方向进行分割、无连续布局、为组件使用两个按钮的分割面板
JSplitPane(int orient) 创建一个在指定方向进行分割且无连续布局的分割面板
JSplitPane(int orient, Component leftC, Component rightC) 创建一个在指定方向进行分割、不连续重绘的指定组件的分割面板

从上表我们可以看出,JSplitPane 的构造方法中包含有参数 orient,该参数用于指定分割面板的分割方向。

JSplitPane 类的分割方向说明如下表所示:
字段| 描述
JSplitPane.HORIZONTAL_SPLIT | 表示在水平方向上对分割面板进行分割
JSplitPane.VERTICAL_SPLIT | 表示在垂直方向上对分割面板进行分割

创建分割面板对象,示例代码如下:

JSplitPane splitPane1 = new JSplitPane();
JSplitPane splitPane1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
JSplitPane splitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);

② 使用分割面板
JSplitPane 创建的对象是一个分割面板,JSplitPane 类提供了一些方法,可以完成分割面板的常用操作。

该类的常用方法如下表所示:

方法 描述
getBottomComponent() 返回分隔条下面或右边的组件
getDividerSize() 返回分隔条的大小
getLeftComponent() 返回分隔条左边或上面的组件
getRightComponent() 返回分隔条右边或下面的组件
getTopComponent() 返回分隔条上面或左边的组件
remove(Component comp) 移除窗格中的子组件 comp
setBottonComponent(Component comp) 将组件设置到分隔条的下面或右边

下面我们来创建一个分割面板对象并使用它,示例代码如下:

import javax.swing.*;

public class JSplitPaneFrame extends JFrame {
    JSplitPane splitPane1;
    JButton topButton, bottomButton;

    public JSplitPaneFrame(String title) {
        super(title);

        //创建水平分割面板
        splitPane1 = new JSplitPane();

        //创建按钮
        topButton = new JButton("顶部按钮");
        bottomButton = new JButton("底部按钮");

        //在分割面板中添加按钮
        splitPane1.setTopComponent(topButton);
        splitPane1.setBottomComponent(bottomButton);

        //设置分割面板显示UI小部件
        splitPane1.setOneTouchExpandable(true);

        add(splitPane1);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 360, 300);
        setVisible(true);
    }

    public static void main(String args[]) {
        new JSplitPaneFrame("JSplitPane");
    }
}

运行该实例,结果如下:


image.png

这个例子首先创建了一个在水平方向进行分割、无连续布局、包含有两个按钮的分割面板,然后把右侧的分割面板设置为在垂直方向进行分割的分割面板,接着创建了两个按钮,并把这两个按钮放分别放到水平分割面板的左部和右部。

<mark style="box-sizing: border-box; outline: 0px; user-select: text !important; background-color: rgb(248, 248, 64); color: rgb(0, 0, 0); overflow-wrap: break-word;">注意</mark>
使用分割面板可以将窗体分割成两个部分,但只能是两个部分,也就是各部分之间只能添加一个组件,要想进行扩充,可以在面板中再添加面板组件。

下面我们再来看一个比较复杂的实例,创建窗体,在该类中创建一个水平分割面板和一个垂直分割面板,并在水平分割面板的左侧及垂直分割面板的上面和下面各放一个标签,然后把垂直分割面板放到水平分割面板的右侧。

import javax.swing.*;

public class JSplitPaneFrame extends JFrame {
    JSplitPane hsplitPane,vsplitPane;
    JButton leftButton;
    JLabel topLabel,bottomLabel;

    public JSplitPaneFrame(String title) {
        super(title);

        //创建在水平方向分割的分割面板
        hsplitPane = new JSplitPane();

        //创建在垂直方向分割的分割面板
        vsplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);

        //创建按钮
        leftButton = new JButton("左边");

        //创建标签
         topLabel = new JLabel("上面");
        bottomLabel = new JLabel("下面");

        //在水平分割面板的左边放置按钮
        hsplitPane.setLeftComponent(leftButton);

        //在水平分割面板的右边放置垂直分割面板
        hsplitPane.setRightComponent(vsplitPane);

        //设置水平分割面板的分割条距上边为40像素
        hsplitPane.setDividerLocation(40);

        //在垂直分割面板上放置标签
        vsplitPane.setTopComponent(topLabel);
        vsplitPane.setBottomComponent(bottomLabel);

        //设置垂直分割面板的分割条距上边为40像素
        vsplitPane.setDividerLocation(40);

        //将水平分割面板添加到容器中
        add(hsplitPane);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 360, 300);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new JSplitPaneFrame("JSplitPane");
    }
}

运行该实例,结果如下:


image.png

🐶 选项卡面板:JTabbedPane

选项卡面板可以在窗体中放置多个标签页,每个标签页相当于一个与此选项卡大小相同的容器,在每个标签页中都可以放置一个或多个组件,使每个标签页实现不同页面的效果,使用 javax.swing.JTabbedPane 类可创建一个选项卡面板。

① 创建选项卡面板
使用选项卡面板的好处是,用户通过单击具有给定标题或图片的选项卡在一组组件之间进行切换。创建选项卡面板,首先需要创建 JTabbedPane 对象。

JTabbedPane 类的构造方法如下表所示:

构造方法 功能
JTabbedPane() 创建一个在上面显示标签,布局方式为自动换行的空选项卡
JTabbedPane(int tabPlace) 创建一个在指定位置显示标签,布局方式为自动换行的空选项卡
JTabbedPane(int tabPlace, int tabLayout) 创建一个在指定位置显示标签和具有指定布局策略的空选项卡

在构造方法中,参数 tabPlace 是用于指定选项卡标签显示位置的字段,参数 tabLayout 是指定选项卡面板标签布局的字段。

tabPlace 参数的常用字段说明如下表所示:

字段 描述
JTabbedPane.TOP 表示在选项卡的上边位置显示标签
JTabbedPane.BOTTOM 表示在选项卡的下边位置显示标签
JTabbedPane.LEFT 表示在选项卡的左侧位置显示标签
JTabbedPane.RIGHT 表示在选项卡的右侧位置显示标签
JTabbedPane.WRAP_TAB_LAYOUT 当选项卡的一行或一列不能显示所有标签时,标签会自动换行或换列

创建窗体,并在该类中创建选项卡面板,示例代码如下:

// 创建一个在上面显示标签,布局方式为自动换行的空选项卡
JTabbedPane tabbedPane1 = new JTabbedPane();

// 创建一个在左侧显示标签,布局方式为自动换行的空选项卡
JTabbedPane tabbedPane2 = new JTabbedPane(JTabbedPane.LEFT);

② 使用选项卡面板
在使用选项卡面板时,可以向面板中添加标题、图标等,使选项卡面板看上去更加漂亮。JTabbedPane 提供了一些方法来实现选项卡面板的常用操作。

JTabbedPane 类的常用方法如下表所示:

方法 描述
addTab(String title, Component comp) 添加一个标题为 title 且没有图标的选项卡
addTab(String title, Icon icon, Component comp) 添加一个标题为 title,图标为 icon 的选项卡
addTab(String title, Icon icon, Component comp, String tip) 添加由标题为 title,图标为 icon,工具提示文本为 tip 组成的选项卡
getSelectedComponent() 返回选项卡面板当前选中的选项卡
getSelectedIndex() 返回当前选中的选项卡的索引

下面让我们来看一个使用 JTabbedPane 的实例。
要求:创建窗体,然后在窗体中添加选项卡面板,在第一个选项卡面板中添加一个按钮,在第二个选项卡面板中添加复选框,在第三个选项卡面板中添加文本域,在第四个选项卡面板中添加单选按钮,此外需要准备 4 个图标。

import javax.swing.*;

public class JTabbedPaneFrame extends JFrame {
    JTabbedPane tabbedPane;
    JButton button;
    Icon icon1, icon2, icon3, icon4;
    JCheckBox checkBox;
    JTextArea textArea;

    public JTabbedPaneFrame(String title) {
        super(title);

        //创建一个在上面显示标签,布局方式为自动换行的空选项卡
        tabbedPane = new JTabbedPane();

        //创建按钮
        button = new JButton("我是一个按钮");

        //实例化图标对象
        icon1 = new ImageIcon("C:\\Users\\15269\\Desktop\\1.ico");
        icon2 = new ImageIcon("C:\\Users\\15269\\Desktop\\1.ico");
        icon3 = new ImageIcon("C:\\Users\\15269\\Desktop\\1.ico");
        icon4 = new ImageIcon("C:\\Users\\15269\\Desktop\\1.ico");

        //添加选项卡
        tabbedPane.addTab("选项卡一", icon1, button, "这里使用了按钮");

        checkBox = new JCheckBox("复选框");
        tabbedPane.addTab("选项卡二", null, checkBox, null);
        tabbedPane.setIconAt(1, icon2);      //为第二个选项卡添加标签图标

        textArea = new JTextArea("文本域");
        tabbedPane.addTab("选项卡三", icon3, textArea, null);
        tabbedPane.setToolTipTextAt(2, "这里使用了文本域");     //为第三个选项卡添加工具提示文本

        JRadioButton radioButton = new JRadioButton("单选按钮");
        tabbedPane.addTab("选项卡四", icon4, radioButton, null);

        add(tabbedPane);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 360, 300);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new JTabbedPaneFrame("JTabbedPane");
    }
}

运行该实例,结果如下:


image.png

🐱 布局方式

Swing 中的每个组件在容器中都有一个具体的位置和大小,在容器中摆放各种组件时很难判断其具体的位置和大小。

布局管理器提供了 Swing 组件摆放在容器中的方法,实现了基本的布局功能。和程序员直接在容器中控制 Swing 组件的位置和大小相比,使用布局管理器要方便得多,同时能够有效地处理整个窗体的布局。

Swing 提供的常用布局管理器包括流布局管理器、边界布局管理器和网格布局管理器等。

🐶 随心所欲绝对布局:setLayout(null)

Swing 中,除了使用布局管理器之外,也可以使用绝对布局。绝对布局,顾名思义,就是硬性指定组件在容器中的位置和大小,可以采用绝对坐标的方式来指定组件的位置。

使用绝对布局只需要两步:
使用 Container.setLayout(null) 方法取消布局管理器,如果你的窗体继承了 JFrame 类,那么这一步写 setLayout(null) 就行。
使用 Component.setBounds() 方法设置每个组件的大小与位置。

下面我们来看一个实例。
要求:在项目中创建继承 JFrame 窗体组件的 AbsolutePosition 类,然后设置布局管理器为 null,即绝对定位的布局方式,并创建两个按钮组件,接着将按钮分别定位在不同的窗体位置上。

import javax.swing.*;

public class AbsolutePosition extends JFrame {
    JButton button1, button2;

    public AbsolutePosition(String title) {
        super(title);

        //设置为绝对布局
        setLayout(null);

        //实例化按钮
        button1 = new JButton("按钮1");
        button1.setBounds(30,40,90,30);

        button2 = new JButton("按钮2");
        button2.setBounds(120,160,110,30);

        //把按钮添加到容器中
        add(button1);
        add(button2);

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 360, 300);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new AbsolutePosition("AbsolutePosition");
    }
}

运行本实例,结果如下:


image.png

在本实例中,窗体的大小、位置及窗体内组件的大小与位置都被进行了绝对布局的操作。绝对布局使用 setBounds(int x, int y, int width, int height) 方法进行设置。

如果是窗体对象调用 setBounds() 方法,则它的参数 xy 代表这个窗体在整个屏幕(也就是你的电脑屏幕)上出现的位置,widthheight 代表这个窗体的宽与长。

如果是窗体内的组件调用 setBounds() 方法,则它的参数 xy 代表这个组件在整个窗体中摆放的位置,widthheight 代表这个组件的大小。

值得注意的是,在使用绝对布局之前,需要调用 setLayout(null) 方法告知编译器这里不再使用布局管理器。

🐶 默认的边界布局:BorderLayout

布局管理器将组件布局排列在东、西、南、北、中 5 个区域,每个区域可以放置一个组件,也可以放置包含其他组件的容器。

该布局管理器的布局结构如下图所示:


image.png

下面我们来看一个在容器中设置边界布局管理器的实例,在本实例中分别在容器的东、南、西、北、中区域添加 5 个按钮。

要求:在项目中创建 BorderLayoutPosition 类,该类继承 JFrame 类成为窗体组件,然后设置该窗体的布局管理器使用 BorderLayout 类的实例对象。

import javax.swing.*;
import java.awt.*;

public class BorderLayoutPosition extends JFrame {
    //定义一个组件摆放位置的数组
    String[] border;

    //定义一个按钮名称的数组
    String[] buttonName;

    public BorderLayoutPosition(String title) {
        super(title);

        //设置为边界布局器
        setLayout(new BorderLayout());

        border = new String[]{BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.WEST, BorderLayout.EAST, BorderLayout.CENTER};

        buttonName = new String[]{"north button", "south button", "west button", "east button", "center button"};

        for (int i = 0; i < border.length; i++) {
            //在容器中添加按钮,并设置按钮布局
            add(border[i], new JButton(buttonName[i]));
        }

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 360, 300);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new BorderLayoutPosition("BorderLayoutPosition");
    }
}

运行本实例,结果如下:


image.png

本实例将布局及组件名称分别放置在数组中,然后设置容器使用边界布局管理器,最后通过循环将按钮添加至容器中,并设置组件布局。add() 方法提供在容器中添加组件的功能,并同时设置组件的摆放位置。

🐶 奇妙的网格布局:GridLayout

网格布局管理器可以将组件以网格的形式排列。使用网格布局,容器将被分成大小相等的矩形,每个矩形区域中可以放置一个组件,这样放置的组件就像表格中的单元格一样整齐地排列。用户可以设置网格布局管理器的行数和列数,创建不同大小的网格布局管理器。

网格管理器的布局结构如下图所示:


image.png

① 创建网格布局管理器
GridLayout 类表示网格布局管理器,容器通过 setLayout() 方法将容器设置为网格布局的形式。

GridLayout 类的常用构造方法说明如下图所示:

构造方法 描述
GridLayout() 创建默认的网格布局管理器,这个默认的管理器对象将组件排列在一行或一列中
GridLayout(int rows, int cols) 创建具有指定行数和列数的网格布局管理器,布局管理器将为所有组件分配相同大小的空间
GridLayout(int rows, int cols, int hgap, int vgap) 创建具有指定行数、列数和组件间距的网格布局管理器,布局管理器将为所有组件分配相同大小的空间

② 使用网格布局管理器
创建网格布局管理器后,用户还可以调用 GridLayout 类的方法改变网格的行数和列数等属性。

GridLayout 类的常用方法如下表所示:

方法 描述
setRows(int rows) 设置布局管理器中的行数
setColumns(int cols) 设置布局管理器中的列数
setHgap(int hgap) 将组件之间的水平间距设置为指定值
setVgap(int vgap) 将组件之间的垂直间距设置为指定值

下面我们来看一个实例。
要求:在项目中创建 GridLayoutPosition 类,该类继承 JFrame 类成为窗体组件,然后设置该窗体使用 GridLayout 布局管理器。

import javax.swing.*;
import java.awt.*;

public class GridLayoutPosition extends JFrame {

    public GridLayoutPosition(String title) {
        super(title);

        //设置容器使用网格布局管理器,设置7行3列的网格
        setLayout(new GridLayout(7, 3, 5, 5));

        //循环添加按钮
        for (int i = 0; i < 21; i++) {
            add(new JButton("button" + i));
        }

        //设置窗口风格
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 360, 300);
        setVisible(true);
    }

    //main方法
    public static void main(String args[]) {
        new GridLayoutPosition("GridLayout");
    }
}

运行本实例,结果如下:


image.png

从本实例的运行结果中可以看到,窗体中的布局呈现出一个 73 列的网格,添加到该布局中的组件被放置在网格中。如果尝试去改变窗体的大小,那么我们就会发现其中的组件大小也会相应地改变。

🐶 像水一样的流式布局:FlowLayout

流式布局管理器是最基本的布局管理器。使用流式布局的容器像 “流” 一样按指定的方向排放控件,直到占据了这一行的所有空间,然后再向下移动一行。FlowLayout 类表示流式布局。

FlowLayout 类常用的构造方法说明如下表所示:

构造方法 描述
FlowLayout() 构造一个新的 FlowLayout 对象,居中对齐,默认的水平和垂直间距是 5 个单位
FlowLayout(int align) 创建具有指定对齐方式的 FlowLayout 对象
FlowLayout(int align, int hgap, int vgap) 创建具有指定对齐方式及指定的水平和垂直间隙的 FlowLayout 对象

在构造方法中,参数 align 表示组件排放的对齐方式,该参数的可选值如下:
FlowLayout.LEFT:在单行中左对齐。
FlowLayout.CENTER:在单行中居中对齐。
FlowLayout.RIGHT:在单行中右对齐。

下面我们通过一个例子来更好地理解 FlowLayout 在项目中创建 MyFrame 类,该类继承 JFrame 类成为窗体组件,然后设置该窗体使用 FlowLayout 布局管理器进行组件布局。

import java.awt.*;
import javax.swing.*;

public class MyFrame extends JFrame {

    public MyFrame(String title) {
        super(title);

        //设置为流式布局
        setLayout(new FlowLayout());

        //在容器中添加10个按钮
        for(int i=0;i<10;i++){
            add(new JButton("按钮" + (i+1)));
        }

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400, 300, 260, 200);
        setVisible(true);
    }

    public static void main(String[] args) {
        new MyFrame("FlowLayout");
    }
}

本实例的运行结果如下图所示:


image.png

由于流式布局控件的排放位置与窗体的宽度有关,调整窗体后的运行结果如下图所示:


image.png

🐱 事件监听器

在窗体中只添加组件是没有任何意义的,因此需要为组件绑定事件。在应用软件中,事件处理随处可见,如当用户单击关闭按钮时,就会触发关闭窗体的事件处理。

🐶 事件监听器概述

GUI 事件处理机制是指在 GUI 控件中添加的各种操作,如移动鼠标、单击按钮等。事件处理机制就是指 GUI 窗体与用户的交互。

在事件处理机制中,需要理解下面三个重要的概念。
(1) 事件:将用户对控件的一个操作称为一个事件,如单击按钮、关闭窗体等。
(2) 事件源:发生事件的控件就是事件源,如当用户单击按钮时,这个按钮就是事件源。
(3) 事件处理器:负责处理事件的方法,Java 程序对事件处理的方法放在一个类对象中,这个类对象就是事件监听器。

事件监听器首先与控件建立关联,当控件受到外界作用时,就会产生一个相应的事件对象,并把此对象传给与之关联的事件处理器,事件处理器就会被启动并运行相关的代码来处理该事件。

Java 语句中的事件也是对象,一类事件对应一个 AWT 事件类,通过查阅 JDK 文档中的 java.awt.event 包,可了解所有的事件类。

🐶 动作事件监听器:ActionListener

动作事件是经常使用的处理事件,如单击按钮、选择菜单选项等都会发生动作事件。Java 中的动作事件由 ActionEvent 类表示,与动作事件对应的事件处理接口为 ActionListener 接口。

当控件发生动作事件后,ActionListener 接口中的方法会被自动调用,该接口中只有一个方法 actionPerformed()

下面我们以给按钮添加动作事件为例,介绍为控件添加动作事件的步骤。
首先,我们定义一个实现事件监听器的类,创建 ActionDemo 类,该类实现 ActionListener 接口,代码如下。

public class ActionDemo implements ActionListener {

    public void actionPerformed(ActionEvent e) {
        // 此处添加处理事件的代码
    }
}

然后,向事件源注册监听者对象,控件可通过 addActionListener() 方法注册事件监听器,向按钮注册动作事件监听器的代码如下。

button.addActionListener(ad);

上段代码中的 ad 为动作事件监听器接口对象,将动作事件监听对象注册给按钮后,有关事件处理的工作就完成了。此时,当用户单击按钮时,就会有相应的结果出现。

下面我们通过一个完整的实例来进一步了解动作事件监听器的使用。
在窗体中添加关闭按钮,并为该按钮绑定单击事件,实现当用户单击该按钮时,将窗体关闭的功能。

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

public class ActionEventDemo extends JFrame {
    JPanel panel;
    JButton button;

    public static void main(String[] args) {
        new ActionEventDemo("ActionEvent");
    }

    public ActionEventDemo(String title){
        super(title);

        //定义面板对象
        panel = new JPanel();
        setContentPane(panel);

        //定义按钮对象
        button = new JButton("点我关闭窗口");

        //绑定按钮的单击事件
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        panel.add(button);

        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        setBounds(400,300,360,260);
        setVisible(true);       //设置窗口可见
    }
}

本实例的事件监听是通过直接创建 ActionListener 实例实现的,运行结果如下图所示。

image.png

🐶 焦点事件监听器:FocusListener

在实际项目开发中焦点事件监听器的应用也比较广泛,如使光标焦点离开一个文本框时弹出一个对话框,或者将焦点返回给该文本框等,此时就需要为组件添加焦点事件监听器,这个监听器需要实现 FocusListener 接口。该接口定义了两个方法,分别为 focusLost()focusGained() 方法,其中,focusLost() 方法是在组件失去焦点时调用,focusGained() 方法是在组件获取焦点时调用。

下面我们来看一个实例,在窗体中添加文本框与按钮组件,然后为文本框组件绑定焦点事件,当文本框获得焦点时,组件颜色变为青蓝色,当文本框失去焦点时,组件颜色变为绿色。

import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;

public class FocusEventDemo extends JFrame {
    JPanel panel;
    JTextField t1,t2;

    public static void main(String[] args) {
        new FocusEventDemo("FocusEvent");
    }

    public FocusEventDemo(String title){
        super(title);

        //定义面板对象
        panel = new JPanel();
        setContentPane(panel);

        t1 = new JTextField(15);
        t2 = new JTextField(15);

        t1.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                //设置组件背景色为CYAN
                t1.setBackground(Color.CYAN);
            }

            @Override
            public void focusLost(FocusEvent e) {
                t1.setBackground(Color.GREEN);
            }
        });

        panel.add(t1);
        panel.add(t2);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(400,300,260,260);
        setVisible(true);       //设置窗口可见
    }
}

得到焦点时

image.png

失去焦点时

image.png
上一篇下一篇

猜你喜欢

热点阅读