Java Swing 编程全面解析:从 AWT 到 Swing 的进化之路
目录
前言
一、AWT 简介
1. 什么是 AWT?
2. AWT 的基本组件
3. AWT 编程示例
二、Swing 的诞生与进化
1. Swing 的特点
2. Swing 和 AWT 的主要区别
3. Swing 的基本组件
三、Swing 编程的基础示例
四、Swing 的高级功能
1. 布局管理器
2. 事件监听
3. 自定义外观
五、综合案例:计算器
六、总结

前言
Java 提供了强大的图形用户界面(GUI)工具,用于创建跨平台的桌面应用程序。从早期的 AWT(Abstract Window Toolkit)到更先进的 Swing,Java GUI 编程逐步演进,解决了跨平台一致性、组件丰富性以及性能等问题。本篇博客将详细讲解从 AWT 到 Swing 的过渡。
一、AWT 简介
1. 什么是 AWT?
AWT(Abstract Window Toolkit)是 Java 1.0 提供的一个 GUI 工具包,它使用系统的本地 GUI 组件(如 Windows 的按钮、macOS 的窗口等)来构建界面。由于 AWT 依赖于本地操作系统的组件,因此具有如下特点:
- 优点:
- 跨平台支持:能在不同操作系统中运行。
- 轻量级:组件直接调用本地系统资源。
- 缺点:
- 限制较多:组件功能单一,难以满足复杂 GUI 的需求。
- 外观不一致:不同操作系统上的显示效果可能不同。
- 不灵活:自定义组件的能力有限。
2. AWT 的基本组件
AWT 提供了一些基本组件,例如:
- Container:顶级容器(如
Frame、Panel)用于容纳其他组件。 - Component:基本组件(如
Button、Label、TextField)。 - Layout Manager:布局管理器,用于控制组件的排列方式。
3. AWT 编程示例
import java.awt.*;public class AWTExample {public static void main(String[] args) {// 创建 Frame 窗口Frame frame = new Frame("AWT Example");frame.setSize(300, 200);frame.setLayout(new FlowLayout());// 添加组件Label label = new Label("AWT Label");Button button = new Button("Click Me");frame.add(label);frame.add(button);// 显示窗口frame.setVisible(true);}
}
二、Swing 的诞生与进化
为了弥补 AWT 的不足,Java 在 JDK 1.2 中引入了 Swing。Swing 是基于 AWT 的扩展,它不仅解决了 AWT 的缺陷,还大大增强了 GUI 开发的能力。
1. Swing 的特点
- 轻量级组件:Swing 的组件不依赖于本地操作系统,而是用纯 Java 实现。
- 丰富的组件库:提供了大量高级组件(如
JTable、JTree、JTabbedPane等),能够满足复杂的用户界面需求。 - 可定制性:Swing 支持基于
Pluggable Look-and-Feel的外观定制,可以实现跨平台一致的用户界面。 - 事件驱动模型:通过事件监听器机制处理用户交互。
2. Swing 和 AWT 的主要区别
| 特性 | AWT | Swing |
|---|---|---|
| 组件实现 | 依赖本地操作系统的组件 | 纯 Java 实现(轻量级组件) |
| 组件外观 | 外观由操作系统决定 | 支持跨平台外观,可自定义 |
| 线程模型 | 非线程安全 | 大多数操作需要在事件调度线程中完成 |
| 组件种类 | 基本组件,如 Button、Label | 丰富组件,如 JButton、JLabel |
| 功能扩展性 | 功能有限,扩展困难 | 支持高级功能,易于扩展 |
3. Swing 的基本组件
Swing 的组件以 J 开头,例如:
- 顶级容器:
JFrame、JDialog、JApplet。 - 基本组件:
JButton、JLabel、JTextField、JCheckBox。 - 高级组件:
JTable、JTree、JTabbedPane、JScrollPane。
三、Swing 编程的基础示例
以下是一个使用 Swing 创建简单窗口的示例:
import javax.swing.*;public class SwingExample {public static void main(String[] args) {// 创建 JFrame 窗口JFrame frame = new JFrame("Swing Example");frame.setSize(300, 200);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 添加组件JLabel label = new JLabel("Hello, Swing!");JButton button = new JButton("Click Me");frame.setLayout(new java.awt.FlowLayout());frame.add(label);frame.add(button);// 显示窗口frame.setVisible(true);}
}
四、Swing 的高级功能
1. 布局管理器
Swing 提供了多种布局管理器,用于控制组件在容器中的排列方式:
- FlowLayout:按添加顺序从左到右排列。
- BorderLayout:分为东、南、西、北、中五个区域。
- GridLayout:以网格形式排列组件。
- BoxLayout:允许组件在垂直或水平方向排列。
frame.setLayout(new BorderLayout());
frame.add(new JButton("North"), BorderLayout.NORTH);
frame.add(new JButton("South"), BorderLayout.SOUTH);
frame.add(new JButton("East"), BorderLayout.EAST);
frame.add(new JButton("West"), BorderLayout.WEST);
frame.add(new JButton("Center"), BorderLayout.CENTER);
2. 事件监听
Swing 使用事件监听器来处理用户操作,例如按钮点击、鼠标移动等。
示例:按钮点击事件
button.addActionListener(e -> System.out.println("Button clicked!"));
3. 自定义外观
Swing 支持修改外观(Look-and-Feel),可以通过以下代码设置跨平台外
try {UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
} catch (Exception e) {e.printStackTrace();
}
五、综合案例:计算器
以下是一个简单的 Swing 计算器示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;public class Calculator {public static void main(String[] args) {JFrame frame = new JFrame("Calculator");frame.setSize(400, 500);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setLayout(new BorderLayout());// 显示区域JTextField display = new JTextField();display.setFont(new Font("Arial", Font.BOLD, 24));frame.add(display, BorderLayout.NORTH);// 按钮区域JPanel buttonPanel = new JPanel();buttonPanel.setLayout(new GridLayout(4, 4));String[] buttons = {"7", "8", "9", "/","4", "5", "6", "*","1", "2", "3", "-","C", "0", "=", "+"};for (String text : buttons) {JButton button = new JButton(text);button.setFont(new Font("Arial", Font.BOLD, 20));buttonPanel.add(button);// 按钮事件监听button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String command = e.getActionCommand();if (command.equals("=")) {// 计算结果try {display.setText(evaluateExpression(display.getText()));} catch (Exception ex) {display.setText("Error");}} else if (command.equals("C")) {// 清空输入框display.setText("");} else {// 更新显示display.setText(display.getText() + command);}}});}frame.add(buttonPanel, BorderLayout.CENTER);// 显示窗口frame.setVisible(true);}// 方法:计算输入的数学表达式private static String evaluateExpression(String expression) {// 使用栈进行数学表达式的求值Stack<Double> values = new Stack<>();Stack<Character> operators = new Stack<>();// 处理输入的表达式for (int i = 0; i < expression.length(); i++) {char ch = expression.charAt(i);// 跳过空格if (ch == ' ') continue;// 如果是数字,处理多位数if (Character.isDigit(ch)) {StringBuilder num = new StringBuilder();while (i < expression.length() && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) {num.append(expression.charAt(i));i++;}i--; // 回退一个字符values.push(Double.parseDouble(num.toString()));} // 如果是左括号,压入栈else if (ch == '(') {operators.push(ch);} // 如果是右括号,解决括号中的内容else if (ch == ')') {while (operators.peek() != '(') {values.push(applyOperation(operators.pop(), values.pop(), values.pop()));}operators.pop(); // 弹出 '('} // 如果是运算符,处理优先级并执行运算else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {while (!operators.isEmpty() && hasPrecedence(ch, operators.peek())) {values.push(applyOperation(operators.pop(), values.pop(), values.pop()));}operators.push(ch);}}// 处理剩下的运算符while (!operators.isEmpty()) {values.push(applyOperation(operators.pop(), values.pop(), values.pop()));}// 最终结果return String.valueOf(values.pop());}// 方法:检查当前运算符的优先级private static boolean hasPrecedence(char op1, char op2) {if (op2 == '(' || op2 == ')') return false;return (op1 != '*' && op1 != '/') || (op2 != '+' && op2 != '-');}// 方法:执行基本的算术运算private static double applyOperation(char op, double b, double a) {switch (op) {case '+': return a + b;case '-': return a - b;case '*': return a * b;case '/': if (b == 0) throw new UnsupportedOperationException("Cannot divide by zero");return a / b;}return 0;}
}
后续会模拟一个跟手机差不多的计算器。
六、总结
Java Swing 的出现极大地提升了 Java GUI 编程的能力,它克服了 AWT 的局限,提供了更强大的组件库和更高的灵活性。在实际开发中,Swing 仍然是构建桌面应用程序的常用工具,尽管随着 JavaFX 的发展,Swing 的使用场景有所减少,但依然是学习 Java GUI 编程的良好起点。
相关文章:
Java Swing 编程全面解析:从 AWT 到 Swing 的进化之路
目录 前言 一、AWT 简介 1. 什么是 AWT? 2. AWT 的基本组件 3. AWT 编程示例 二、Swing 的诞生与进化 1. Swing 的特点 2. Swing 和 AWT 的主要区别 3. Swing 的基本组件 三、Swing 编程的基础示例 四、Swing 的高级功能 1. 布局管理器 2. 事件监听 3…...
mysql数据库启动出现Plugin ‘FEEDBACK‘ is disabled.问题解决记录
本人出现该问题的环境是xampp,异常关机,再次在xampp控制面板启动mysql出现该问题。出现问题折腾数据库之前,先备份数据,将mysql目录下的data拷贝到其他地方,这很重要。 然后开始折腾。 查资料,会发现很多…...
2025年大模型对智能硬件发展的助力与创新创意
随着人工智能(AI)技术,尤其是大模型的快速进步,智能硬件领域正在经历前所未有的变革。到2025年,大模型不仅能为智能硬件提供强大的算法支持,还能通过数据处理、智能决策和系统集成等方面的创新,推动硬件设备的性能提升和功能拓展。本文将从多个维度分析大模型对智能硬件…...
Tensor 基本操作1 unsqueeze, squeeze, softmax | PyTorch 深度学习实战
本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 目录 创建 Tensor常用操作unsqueezesqueezeSoftmax代码1代码2代码3 argmaxitem 创建 Tensor 使用 Torch 接口创建 Tensor import torch参考:https://pytorch.org/tutorials/beginn…...
Python - itertools- pairwise函数的详解
前言: 最近在leetcode刷题时用到了重叠对pairwise,这里就讲解一下迭代工具函数pairwise,既介绍给大家,同时也提醒一下自己,这个pairwise其实在刷题中十分有用,相信能帮助到你。 参考官方讲解:itertools --- 为高效循…...
Docker可视化管理工具Portainer
Portainer简介 Portainer 是一个轻量级的、开源的容器管理工具,提供了一个直观的 Web 用户界面(UI),用于管理 Docker 和 Kubernetes 环境。它简化了容器的部署、监控和管理,特别适合不熟悉命令行操作的用户或团队。 …...
WPF实战案例 | C# WPF实现大学选课系统
WPF实战案例 | C# WPF实现大学选课系统 一、设计来源1.1 主界面1.2 登录界面1.3 新增课程界面1.4 修改密码界面 二、效果和源码2.1 界面设计(XAML)2.2 代码逻辑(C#) 源码下载更多优质源码分享 作者:xcLeigh 文章地址&a…...
leetcode 面试经典 150 题:有效的括号
链接有效的括号题序号20题型字符串解法栈难度简单熟练度✅✅✅ 题目 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须…...
python学opencv|读取图像(三十九 )阈值处理Otsu方法
【1】引言 前序学习了5种阈值处理方法,包括(反)阈值处理、(反)零值处理和截断处理,还学习了一种自适应处理方法,相关文章链接为: python学opencv|读取图像(三十三)阈值处理-灰度图像-CSDN博客 python学o…...
GBase8c aes_encrypt和aes_decrypt函数
在数据库中,aes_encrypt和aes_decrypt函数进行加解密时使用的块加密模式。 GBase8c 与 MySQL 的aes_encrypt和aes_decrypt函数区别: 1、GBase8c 中的初始化向量init_vector不能为空 2、MySQL的加密模块block_encryption_mode 为aes-128-ecb,…...
【2024年华为OD机试】(B卷,100分)- 数据分类 (Java JS PythonC/C++)
一、问题描述 题目描述 对一个数据a进行分类,分类方法为: 此数据a(四个字节大小)的四个字节相加对一个给定的值b取模,如果得到的结果小于一个给定的值c,则数据a为有效类型,其类型为取模的值;如果得到的结果大于或者等于c,则数据a为无效类型。 比如一个数据a=0x010…...
机器学习 vs 深度学习
目录 一、机器学习 1、实现原理 2、实施方法 二、深度学习 1、与机器学习的联系与区别 2、神经网络的历史发展 3、神经网络的基本概念 一、机器学习 1、实现原理 训练(归纳)和预测(演绎) 归纳: 从具体案例中抽象一般规律…...
flutter_学习记录_00_环境搭建
1.参考文档 Mac端Flutter的环境配置看这一篇就够了 flutter的中文官方文档 2. 本人环境搭建的背景 本人的电脑的是Mac的,iOS开发,所以iOS开发环境本身是可用的;外加Mac电脑本身就会配置Java的环境。所以,后面剩下的就是&#x…...
SpringBoot如何自定义Starter ?
大家好,我是锋哥。今天分享关于【SpringBoot如何自定义Starter ?】面试题。希望对大家有帮助; SpringBoot如何自定义Starter ? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Spring Boot 中,自定义 Starter 是一种将应用程…...
前沿技术对比:大模型技术为什么发展远快于区块链技术,中英对照解释
文章目录 前言1、技术复杂性与成熟度 / Technical Complexity and Maturity2.、应用场景与行业需求 / Application Scenarios and Industry Demand3、监管与法律问题 / Regulatory and Legal Issues4、去中心化与网络效应 / Decentralization and Network Effects5、能源消耗与…...
WordPress果果对象存储插件
将网站上的图片等静态资源文件上传至七牛云对象存储,可以减轻服务器文件存储压力,提升静态文件访问速度,从而加速网站访问速度。 支持:阿里云对象存储、华为云对象存储、百度云对象存储、腾讯云对象存储、七牛云对象存储。 下载…...
elk 安装
创建elk网络 docker network create -d bridge elkelasticsearch 创建目录 mkdir -p /data/elasticsearch/{conf,logs,data,plugins}vim /data/elasticsearch/conf/elasticsearch.ymlcluster.name: "es-cluster" network.host: 0.0.0.0 xpack.security.enabled: tr…...
Python 预训练:打通视觉与大语言模型应用壁垒——Python预训练视觉和大语言模型
大语言模型是一种由包含数百亿甚至更多参数的深度神经网络构建的语言模型,通常使用自监督学习方法通过大量无标签文本进行训练,是深度学习之后的又一大人工智能技术革命。 大语言模型的发展主要经历了基础模型阶段(2018 年到2021年)、能力探索阶段(2019年…...
OpenCV相机标定与3D重建(63)校正图像的畸变函数undistort()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 转换图像以补偿镜头畸变。 该函数通过变换图像来补偿径向和切向镜头畸变。 此函数仅仅是 initUndistortRectifyMap(使用单位矩阵 R…...
用 Java 发送 HTML 内容并带附件的电子邮件
实现思路 首先,设置邮件服务器的相关属性,包括是否需要认证、使用的邮件协议、服务器地址、端口等。 创建一个会话对象,使用 Session.getInstance 方法,并提供邮件服务器的属性和认证信息。 创建一个 MimeMessage 对象作为邮件消…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
