# 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` 定义 (``)。这是「样式写了没生效」头号原因 (忘设 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` 米黄背景 + 圆角) - **挑战版**:深/浅双主题切换 ✓(视图菜单「深色主题」)