# Day3 下午参考实现：计算器 QMainWindow + QSS 双主题

> 对应教案 [`OUTLINE_4DAY.md`](../../OUTLINE_4DAY.md) Day3 下午「布局/控件 + QSS 美化」
> + [`ASSIGNMENTS.md`](../../ASSIGNMENTS.md) Day3 下午作业。手工维护，非生成产物。

## 定位：上午版 + QSS 美化

以 [`../calculator_mainwindow/`](../calculator_mainwindow/README.md)（Day3 上午版）为起点，
**只加 QSS**：按键按功能分色、`:hover`/`:pressed` 视觉反馈、深/浅双主题切换。
菜单/停靠窗/状态栏/计算逻辑与上午版完全一致——**QSS 与逻辑正交**，这正是 Day3 下午
「美化」环节要传达的核心。

## 与上午版的差异（集中在 `mainwindow.{h,cpp}` + `themes/`）

| 改动 | 位置 | 内容 |
|---|---|---|
| 双主题样式表（**外部 `.qss` 文件**） | `themes/light.qss`、`themes/dark.qss` | 按键分色 + 伪状态 |
| 资源清单 | `themes.qrc`（`AUTORCC`） | 嵌入 `:/themes/light.qss`、`:/themes/dark.qss` |
| 视图菜单「深色主题」 | `buildMenu()` | `checkable` QAction，`toggled → onToggleTheme` |
| `applyStyle(bool dark)` | `mainwindow.cpp` | `QFile` 读 `.qss` → `qApp->setStyleSheet` 全局切换 |
| 自测加主题断言 | `runSelfTest()` | 切换后 `styleSheet()` 含对应主题标识 |

`calculatordesigner.{h,cpp}` / `expressionevaluator.{h,cpp}` / `widget.ui` 与上午版完全一致。

## QSS 最佳实践（本示例的刻意设计）

1. **样式抽成外部 `.qss` 文件**（而非硬编码 C++ 字符串）：`light.qss` / `dark.qss` 是纯样式，
   由 `themes.qrc` 编译进可执行文件，`mainwindow.cpp` 用 `QFile` 读取后 `qApp->setStyleSheet`
   应用。好处：
   - 设计师/非程序员可直接编辑 `.qss`（不用碰 C++）；
   - 开发期改 `.qss` 重跑即生效（不必改 C++ 重编译）；
   - 多主题物理分文件，编辑器对 `.qss` 有语法高亮。
2. **ID 选择器认 objectName**：`QPushButton#btnEquals { ... }` 命中的前提是控件
   `setObjectName("btnEquals")`——本例 objectName 在 `widget.ui` 定义
   （`<widget class="QPushButton" name="btnEquals">`）。这是「样式写了没生效」头号原因
   （忘设 objectName）的反面教材。
3. **按键分色用功能归类**（DRY）：数字键（`btn0`–`btn9`,`btnDot`）浅蓝、运算键橙、等号绿、
   括号灰、清空退格红——用 ID 选择器分组，比给每个按钮单独写样式更易维护。
4. **伪状态**：`:hover` / `:pressed` 不用手写鼠标事件就能做交互反馈。
5. **`qApp->setStyleSheet` 全局 vs `widget->setStyleSheet` 局部**：本例用全局，一次切换全部
   生效。坑卡：全局样式会被 widget 级样式覆盖，混用易级联失控——故本例只用全局。
6. **主题切换不碰逻辑**：`applyStyle` 只改 `styleSheet`，不动任何业务代码。

## 目录结构
```
calculator_mainwindow_qss/
├── mainwindow.{h,cpp}          # 上午版 + applyStyle(loadQss) 主题切换
├── calculatordesigner.{h,cpp}  # 计算器面板（与上午版一致）
├── expressionevaluator.{h,cpp} # 表达式求值（与上午版一致）
├── widget.ui                   # 面板表单（objectName 在此定义）
├── themes.qrc                  # 资源清单：嵌入两个 .qss
├── themes/
│   ├── light.qss               # 浅色主题样式
│   └── dark.qss                # 深色主题样式
└── README.md
```

## 构建与运行

```bash
cmake --build build --target qt_calculator_mainwindow_qss

# 离屏自测（计算用例 + 主题切换改变 styleSheet 的断言，退出码 0 即全过）
PATH=E:/Qt/Qt5.14.2/5.14.2/mingw73_64/bin:$PATH \
QT_QPA_PLATFORM=offscreen \
  ./build/docs/teaching/examples/qt_calculator_mainwindow_qss.exe; echo "exit=$?"

# 有 GUI 环境：勾选「视图→深色主题」看整体配色切换
./build/docs/teaching/examples/qt_calculator_mainwindow_qss.exe
```

## 验收对照（ASSIGNMENTS.md Day3 下午）

- **基础版**：数字/运算/等号 3 色区分 ✓（本例 5 色，含括号/清空退格）
- **基础版**：布局随窗口缩放不重叠 ✓（`QGridLayout` + `QMainWindow` 区域协议）
- **挑战版**：`:hover`/`:pressed` ✓
- **挑战版**：结果显示框套样式 ✓（`display`/`expressionEdit` 米黄背景 + 圆角）
- **挑战版**：深/浅双主题切换 ✓（视图菜单「深色主题」）
