Java Swing的学习

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

下面将以我和deepseek对话的方式,展示我对java swing的理解和学习过程。

1.问

HelloWorldSwing.java 文件代码如下:

import javax.swing.*;
public class HelloWorldSwing {
    /**{
     * 创建并显示GUI。出于线程安全的考虑,
     * 这个方法在事件调用线程中调用。
     */
    private static void createAndShowGUI() {
        // 确保一个漂亮的外观风格
        JFrame.setDefaultLookAndFeelDecorated(true);

        // 创建及设置窗口
        JFrame frame = new JFrame("HelloWorldSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 添加 "Hello World" 标签
        JLabel label = new JLabel("Hello World");
        frame.getContentPane().add(label);

        // 显示窗口
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // 显示应用 GUI
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
执行以下命令输出结果:

$ javac HelloWorldSwing.java
$ java HelloWorldSwing
详细的解释上面这一段代码,把每一行是干什么的都解释清楚

# HelloWorldSwing.java 代码详解

这是一个简单的 Java Swing 程序,用于创建一个显示"Hello World"的图形用户界面(GUI)窗口。下面我将逐行解释代码的功能:

## 1. 导入语句
```java
import javax.swing.*;
```
- 导入 Java Swing 包中的所有类,Swing 是 Java 的 GUI 工具包,用于创建图形用户界面。

## 2. 类定义
```java
public class HelloWorldSwing {
```
- 定义一个名为 `HelloWorldSwing` 的公共类。

## 3. createAndShowGUI 方法
```java
private static void createAndShowGUI() {
```
- 定义一个私有的静态方法 `createAndShowGUI`,用于创建和显示 GUI。

### 方法内部代码:
```java
JFrame.setDefaultLookAndFeelDecorated(true);
```
- 设置 Swing 使用当前系统的默认外观风格,使窗口看起来更符合操作系统风格。

```java
JFrame frame = new JFrame("HelloWorldSwing");
```
- 创建一个新的 `JFrame` 对象(窗口),标题为 "HelloWorldSwing"。

```java
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
```
- 设置当用户点击窗口的关闭按钮时,程序将退出。

```java
JLabel label = new JLabel("Hello World");
```
- 创建一个 `JLabel` 对象(文本标签),显示文本 "Hello World"。

```java
frame.getContentPane().add(label);
```
- 将标签添加到窗口的内容面板中。

```java
frame.pack();
```
- 自动调整窗口大小,使其刚好能容纳所有组件。

```java
frame.setVisible(true);
```
- 设置窗口可见。

## 4. main 方法
```java
public static void main(String[] args) {
```
- 程序的入口点,Java 虚拟机从这里开始执行程序。

```java
javax.swing.SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        createAndShowGUI();
    }
});
```
- 使用 `SwingUtilities.invokeLater()` 方法将 GUI 创建任务放入事件调度线程(Event Dispatch Thread, EDT)中执行。
- 这是 Swing 编程的最佳实践,因为 Swing 组件不是线程安全的,所有 GUI 操作都应在 EDT 中执行。
- 创建一个匿名 `Runnable` 对象,在其 `run()` 方法中调用 `createAndShowGUI()`。

## 执行命令解释

```bash
$ javac HelloWorldSwing.java
```
- 使用 Java 编译器 `javac` 编译源代码,生成 `HelloWorldSwing.class` 字节码文件。

```bash
$ java HelloWorldSwing
```
- 使用 Java 虚拟机 `java` 运行程序,执行 `main` 方法。

## 程序运行结果

运行程序后,会显示一个标题为 "HelloWorldSwing" 的小窗口,窗口中央显示文本 "Hello World"。窗口有关闭按钮,点击后会退出程序。

这个程序展示了 Java Swing 最基本的组件使用和窗口创建流程,是学习 Java GUI 编程的经典入门示例。

2.问:

什么是事件调度线程EDT,用最通俗的话来解释

答:

# 事件调度线程(EDT)通俗解释

可以把事件调度线程(Event Dispatch Thread, EDT)想象成一家餐厅里唯一的服务员:

1. **唯一的工作人员**:就像餐厅只有一个服务员处理所有顾客请求一样,EDT是Swing中唯一负责处理所有用户界面操作的线程。

2. **按顺序工作**:服务员一次只能处理一个顾客的点单,EDT也是一次只处理一个GUI事件(点击按钮、移动窗口等),按先来后到的顺序。

3. **不能被打断**:如果服务员正在为A桌点单,B桌突然喊他,他也不能立即响应,必须完成当前工作。同样,EDT处理一个事件时,其他事件必须等待。

4. **为什么需要EDT**:如果多个人同时指挥服务员(多线程操作界面),可能会导致混乱(界面卡顿、显示异常)。所以Swing规定所有界面操作必须通过EDT这个"服务员"来完成。

5. **invokeLater就像留纸条**:当你在非EDT线程中想操作界面,就像顾客在服务员忙时写下需求放在柜台(invokeLater),服务员(EDT)会在有空时按顺序处理这些需求。

简单说:EDT就是Swing专门用来处理所有界面操作的"专属服务员线程",所有对界面的操作都必须交给它来做,这样才能保证界面不会出问题。

3.问:

为什么要创建匿名对象Runnable对象

答:

# 为什么要创建匿名 Runnable 对象?

在 `SwingUtilities.invokeLater(new Runnable() {...})` 中创建匿名 `Runnable` 对象主要有以下几个原因:

## 1. 最直接的原因:需要传递代码块给 EDT 执行
- `invokeLater()` 方法需要一个 `Runnable` 对象作为参数
- 我们需要把 `createAndShowGUI()` 这段代码包装成 `Runnable` 才能传给 EDT
- 匿名类是最简洁的实现方式

## 2. 代码简洁性(不需要单独定义具名类)
如果不使用匿名类,代码会变得冗长:
```java
// 需要额外定义一个具名类
class MyRunnable implements Runnable {
    public void run() {
        createAndShowGUI();
    }
}

// 然后在main方法中
public static void main(String[] args) {
    SwingUtilities.invokeLater(new MyRunnable());
}
```
使用匿名类可以避免这种代码膨胀。

## 3. 一次性使用(不需要复用)
- 这段代码只需要在这里使用一次
- 不需要在其他地方复用这个 `Runnable` 实现
- 为这种一次性任务专门创建类文件是过度设计

## 4. 保持逻辑集中
- 把界面创建逻辑(`createAndShowGUI`)和它的执行方式(`invokeLater`)放在一起
- 提高代码可读性,避免跳转到其他类查看实现

## 5. Java 8+ 的替代方案(lambda)
在现代Java中,可以用更简洁的lambda表达式替代:
```java
SwingUtilities.invokeLater(() -> createAndShowGUI());
```
但原理相同,仍然是创建了一个 `Runnable` 的匿名实现。

总结:创建匿名 `Runnable` 对象是为了以最简洁的方式把代码传递给事件调度线程执行,同时保持代码的清晰和集中。

4.问:

什么叫匿名类,匿名类如何定义,有什么好处,用最形象的话解释

答:

# 匿名类的通俗解释

## 🎭 什么是匿名类?
匿名类就像"临时工"或"一次性面具":
- 没有正式的名字(所以叫"匿名")
- 当场定义当场使用
- 用完就"消失"(不需要保存)

## 📝 如何定义匿名类?
语法就像在new对象时直接写实现:
```java
父类/接口 变量名 = new 父类/接口() {
    // 在这里写类的具体实现
    // 可以重写方法或添加新方法
};
```

## 🌰 举个栗子
```java
// 普通类(有名字)
class 正式员工 implements Runnable {
    public void run() {
        System.out.println("正式工干活");
    }
}

// 匿名类(临时工)
Runnable 临时工 = new Runnable() {  // 直接在现场定义
    public void run() {
        System.out.println("临时工干活");
    }
};
```

## 💡 匿名类的三大好处
1. **省事**:不用单独创建.java文件
   - 就像临时叫个外卖,不用专门雇厨师

2. **代码紧凑**:把定义和使用放在一起
   - 就像在需要的地方直接写便条,不用翻到笔记本另一页

3. **保护隐私**:外部访问不到这个类
   - 就像说悄悄话,只有当前代码能听见

## 🆚 对比普通类
|          | 普通类         | 匿名类               |
|----------|--------------|--------------------|
| **名字**  | 有(如MyRunnable) | 无                  |
| **复用**  | 可多次使用       | 一次性使用            |
| **位置**  | 单独文件/位置    | 在使用的地方直接定义    |
| **复杂度**| 可很复杂        | 通常只实现少量方法      |

## 🏁 什么时候用?
✅ 适合:只需要用一次的简单实现
❌ 不适合:需要复用的复杂逻辑

就像:
- 点外卖(匿名类):简单吃一顿
- 请厨师(普通类):长期用餐需求

5.问:

为什么举例子要用Runnable方法,这是一个众所周知的方法吗

答:

# 为什么例子常用Runnable?它很"知名"吗?

是的,`Runnable` 确实是 Java 中最广为人知的接口之一,就像编程界的"明星方法"。这主要有以下几个原因:

## 🏆 Runnable 的"江湖地位"
1. **历史悠久**:自 Java 1.0 (1996年) 就存在,几乎所有 Java 开发者都认识它
2. **简单纯粹**:只有一个方法 `run()`,是函数式接口的典范
3. **无处不在**:
   - 多线程编程的基石(Thread 的构造参数)
   - Swing/JavaFX 事件调度线程的标准用法
   - 线程池任务的基本单位
   - Java 8+ 的 lambda 表达式常用范例

## 🧩 为什么教学爱用 Runnable?
| 原因 | 说明 | 类比 |
|------|------|------|
| **认知度高** | 就像教英语用"Hello World"一样自然 | 编程界的"ABC" |
| **结构简单** | 只有一个方法,不会让初学者分心 | 像乐高基础积木 |
| **实用性强** | 学会后立刻能用在真实项目中 | 像学骑自行车,学会就能上路 |
| **示范性强** | 完美展示接口、多线程等核心概念 | 像化学课的"氢+氧=水"实验 |

## 🌰 现实中的 Runnable
```java
// 多线程启动
new Thread(new Runnable() {
    public void run() {
        System.out.println("线程运行中");
    }
}).start();

// 定时任务
Timer timer = new Timer();
timer.schedule(new TimerTask() { // TimerTask 就是实现了 Runnable
    public void run() {
        System.out.println("定时执行");
    }
}, 1000);

// Java 8 lambda 简化版
Runnable r = () -> System.out.println("现代写法");
```

## 💡 你知道吗?
即使你不直接写 `Runnable`,你在用:
- Android 的 `Handler.post()`
- Spring 的 `@Async`
- JavaScript 的 Promise
这些概念本质上都是 `Runnable` 的思想变体

所以用 `Runnable` 举例,就像用"牛顿定律"解释物理现象一样,是最经典、最不会出错的选择!

6.问:

再举一个例子,能够形象的区分类和匿名类

答:

# 类 vs 匿名类的形象比喻

## 🏭 正式工厂 vs 临时作坊

### 1️⃣ 正式类 - 像注册的工厂
```java
// 正式注册的蛋糕工厂 (有名字、可重复使用)
class CakeFactory {
    public void makeCake() {
        System.out.println("🍰 生产标准蛋糕");
    }
}

// 使用时
CakeFactory factory = new CakeFactory();
factory.makeCake(); // 可以反复调用
```

特点:
- **有正式名称**:`CakeFactory`
- **可重复使用**:可以new多个实例
- **可被继承扩展**:其他类可以继承它
- **代码分离**:通常写在单独文件中

### 2️⃣ 匿名类 - 像临时搭建的作坊
```java
// 临时需求:今天只要做一个特殊蛋糕
Runnable temporaryWorkshop = new Runnable() { // 没有类名!
    public void run() {
        System.out.println("🎂 临时制作草莓蛋糕");
    }
};

temporaryWorkshop.run(); // 只能用这一次
```

特点:
- **没有名字**:只能通过父类/接口类型引用
- **一次性使用**:适合特定场景的临时实现
- **就地定义**:在使用的地方直接编写
- **无法复用**:不能在其他地方new这个类

## 🍰 现实场景对比
**需求**:给不同客户做蛋糕

```java
// 方案1:用正式类(适合长期需求)
class CustomCakeFactory {
    private String flavor;
    
    public CustomCakeFactory(String flavor) {
        this.flavor = flavor;
    }
    
    public void makeCake() {
        System.out.println("制作" + flavor + "蛋糕");
    }
}

// 为常客建立档案
CustomCakeFactory clientA = new CustomCakeFactory("巧克力");
CustomCakeFactory clientB = new CustomCakeFactory("芒果");

// 可以随时为他们做蛋糕
clientA.makeCake(); 
clientB.makeCake();

// ---------------------------------------------------

// 方案2:用匿名类(适合临时订单)
Runnable oneTimeOrder = new Runnable() {
    public void run() {
        System.out.println("临时制作榴莲蛋糕(仅此一次)");
    }
};

// 只为这个特殊订单执行一次
oneTimeOrder.run(); 
```

## 📊 核心区别总结
|          | 正式类                 | 匿名类                  |
|----------|-----------------------|------------------------|
| **名字**  | 有明确类名             | 没有类名                |
| **用途**  | 长期/多次使用          | 一次性/临时使用          |
| **位置**  | 通常单独文件定义       | 在使用处就地定义         |
| **复杂度**| 可以很复杂             | 通常只实现少量方法       |
| **扩展性**| 可以被继承             | 不能被其他类继承         |

就像生活中:
- **正式类**像注册的餐厅,有名字、有固定菜单、可以反复光顾
- **匿名类**像路边摊,临时摆出来做特定小吃,做完就收摊

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值