Files
chouka/第01课-GUI你好窗口.md
2026-05-16 12:05:04 +08:00

254 lines
7.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第 1 课:GUI 你好窗口
> **本课目标**:从一个空空的程序开始,**自己一步一步**让屏幕上弹出一个写着 "欢迎来到抽卡世界!" 的窗口。
>
> **预计时间**30~40 分钟
>
> **学完之后**:你能解释什么是窗口、控件、事件循环,并能凭记忆写出 5~6 行让窗口出现的代码。
---
## 0. 上课前先理理
### 命令行程序 vs GUI 程序
| | 命令行(以前的你) | GUI(现在的你) |
|---------|-----------------------------|----------------------------------|
| 长什么样 | 黑底白字一行行 | 有窗口、按钮、彩色文字 |
| 怎么跑 | 一口气从上跑到下,跑完就退出 | 启动后 **一直在等** 你点鼠标 |
| 怎么输出 | `std::cout << ...` | 把文字 "贴" 在窗口上的便利贴上 |
### 这一课会认识 3 个新朋友
| 名字 | 比喻 | 干什么用 |
|---------------|------------------|-------------------------------------|
| `Fl_Window` | **画纸** | 程序的窗口本体 |
| `Fl_Box` | **便利贴** | 贴在画纸上的一段文字 |
| `Fl::run()` | **不下班的保安** | 让窗口一直待着,等你操作 |
> 💡 还会顺带认识两个 C++ 新写法:`new` 和 `->`。先不用搞懂原理,跟着写就行。
---
## 1. 起步:打开起步骨架,先编译一次
打开 `lesson_gui_1.cpp`。你会看到一个全是 TODO 的骨架。
先在终端里编译一下,确认环境没问题:
**Mac / Linux**
```bash
cmake -B build -DLESSON=1
cmake --build build
./build/gacha1
```
**Windows**
```bash
cmake -B build -DLESSON=1 -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build build --config Release
build\Release\gacha1.exe
```
> 💡 第一次 `cmake -B build -DLESSON=1` 之后,**后面每次只要改了 `.cpp`,运行前两行就够**:
> ```bash
> cmake --build build && ./build/gacha1
> ```
### ✅ 检查点 1
- [ ] 编译没报错
- [ ] 运行后……什么都没发生?**对的**!程序进了 `main`,立刻就 `return 0` 退出了。我们接下来一步步让它"活"起来。
---
## 2. 步骤 1:变出一个空窗口
### 🤔 先想一下
- 一个窗口至少要告诉电脑哪些信息?(提示:长什么样、叫什么)
- 程序跑完 `main` 就结束了——那窗口怎么能"一直待着"呢?
### ✏️ 在 `main` 里加这 3 件事
**(1) 创建窗口对象**:替换掉 `// TODO(步骤 1):在这里创建一个窗口对象 window` 那一行:
```cpp
Fl_Window *window = new Fl_Window(400, 300, "抽卡世界");
```
读法:用 `new` "变出" 一个 `Fl_Window`,宽 400、高 300,标题叫 "抽卡世界"。`window` 是它的名字。
**(2) 显示窗口**:替换掉 `// TODO(步骤 1):告诉窗口"控件加完了"…` 那一行:
```cpp
window->end();
window->show();
```
读法:`->` 念 "的"。`window``end()` 表示"控件加完啦"`window``show()` 是"露面"。
**(3) 让程序"待住"不退出**:把最后的 `return 0;` 改成:
```cpp
return Fl::run();
```
`Fl::run()` 就是那个不下班的保安——它会卡在这里,直到你关闭窗口才返回。
### ▶️ 编译运行
```bash
cmake --build build && ./build/gacha1
```
### ✅ 检查点 2
- [ ] 屏幕上出现一个 400×300 的空白窗口
- [ ] 窗口标题栏写着 "抽卡世界"
- [ ] 关闭窗口,程序退出,终端回到提示符
🎉 你的第一个 GUI 程序!但里面空空的,下一步贴张便利贴上去。
> ❓ 如果没出来:是不是忘了把 `return 0;` 改成 `return Fl::run();`
---
## 3. 步骤 2:在窗口里贴一张便利贴
### 🤔 先想一下
- 贴在窗口里的文字,应该放在窗口的哪个位置?怎么告诉电脑这个位置?
- 文字框本身也是一个"东西",那它要不要 `new` 出来?
### ✏️ 改两个地方
**(1) 顶上的 include 区**:把 `// TODO(步骤 2`:还需要再 `#include 一个头文件` 这行替换成:
```cpp
#include <FL/Fl_Box.H>
```
便利贴在 FLTK 里叫 `Fl_Box`,要先告诉编译器去哪儿找。
**(2) 在 `window->end();` **之前**插入这一行**(替换掉对应的 TODO):
```cpp
Fl_Box *box = new Fl_Box(50, 100, 300, 100, "欢迎来到抽卡世界!");
```
读法:变出一个 `Fl_Box`,位置 (50, 100),宽 300、高 100,文字是 "欢迎来到抽卡世界!"。
### 📐 坐标到底怎么数?
FLTK 的坐标系——和你以前数学课上的不一样,Y 是 **向下** 增大的:
```
(0,0) ──────────── X →
│ (50,100)
│ ↓
│ ┌──────────┐
│ │ 便利贴 │ 宽 300
│ │ │ 高 100
│ └──────────┘
Y
```
- X 从左到右增大
- Y 从上到下增大
- 原点 (0,0) 在窗口左上角
### ▶️ 编译运行
```bash
cmake --build build && ./build/gacha1
```
### ✅ 检查点 3
- [ ] 窗口里出现了 "欢迎来到抽卡世界!"
- [ ] 文字大概在窗口中间偏上的位置
> ❓ 文字看起来很小?没事,下一步搞定字号。
---
## 4. 步骤 3:让字大起来
### ✏️ 在 `new Fl_Box(...)` 那行的**下一行**加:
```cpp
box->labelsize(24);
```
意思是:`box``labelsize`(标签字号)设为 24。
### ▶️ 编译运行
```bash
cmake --build build && ./build/gacha1
```
### ✅ 检查点 4
- [ ] 文字明显变大了
- [ ] 整个窗口看起来终于像个迎宾画面了
🎉 **第 1 课通关!** 你刚刚自己写出了一个完整 GUI 程序。
---
## 5. 玩一玩:改一改看会发生什么
每改一个,记得 **保存 → 编译 → 运行**
1.`400, 300` 改成 `600, 400`。窗口变大了吗?
2.`labelsize(24)` 改成 `36``12``80`。极端值会怎样?
3.`(50, 100, 300, 100)` 里的 `50` 改成 `0`。文字跑哪儿去了?
4. 把窗口标题 `"抽卡世界"` 改成你自己起的名字。
5. **思考题**:怎么让文字 **正好居中**?窗口宽 400,文字框宽 300——X 应该填几?
> 💡 想到答案再往下看:宽 400 减宽 300 等于 100,两边各留 50,所以 X = 50。本课的代码刚好就是居中的。
---
## 6. 课后挑战(选做)
完成以上后还想多玩?挑一个:
- **A. 双便利贴**:在窗口的上、下半部分各放一个 `Fl_Box`,写不同的话。
- **B. 给画纸刷色**:在 `window->end()` 前面加 `window->color(fl_rgb_color(255, 240, 200));`,看看效果。(需要 `#include <FL/fl_draw.H>` 或加在已有头文件里编译试一下,错了就回滚——这就是学编程)
- **C. 思考题**:以前 `std::cout` 一打印就显示,再换一行又能继续打印。GUI 的 `Fl_Box` 行为有什么不一样?
---
## 7. 卡住了?常见小问题
| 现象 | 多半是 |
|------|-------|
| 窗口闪一下就消失 | `return 0;` 没改成 `return Fl::run();` |
| 编译报 "找不到 `Fl_Box`" | 忘了 `#include <FL/Fl_Box.H>` |
| 编译报 "找不到 `FL/Fl.H`" | FLTK 没装好;Mac 跑一下 `brew install fltk cmake` |
| 窗口出来但是全黑/全空白 | `window->show()` 是不是写在 `window->end()` 前面了?顺序反了 |
| 中文变方框 | 文件没存成 UTF-8 编码 |
---
## 8. 偷看老师答案
写不出来、或者想对一下?
```bash
cmake -B build -DLESSON=1 -DUSE_SOLUTION=ON
cmake --build build && ./build/gacha1
```
源文件路径:`solutions/lesson_gui_1.cpp`
**但请尽量自己先动手——卡住 5 分钟以上再看**
---
## 9. 下一课预告
第 2 课:加一个 **按钮**,点一下让窗口里的字变样子。你将第一次见到"用户操作 → 程序响应"的 GUI 核心套路:**回调函数**。
> 📝 学完记得在 `学习进度与状态-GUI.md` 里把第 1 课打勾。
**下一课**`第02课-按钮与回调.md`