Files
scuc-qt-course/docs/teaching/examples/calculator_mainwindow_qss/README.md
T
张宗平 12950da129 QSS 教学示例重构:双主题样式抽离为外部 .qss 资源(QFile 运行时加载)
把原先硬编码在 mainwindow.cpp 里的 kLightQss / kDarkQss 两个 C++ 字符串,
拆成独立的 themes/light.qss、themes/dark.qss,由 themes.qrc(AUTORCC)编译进
可执行文件,applyStyle() 用 QFile 读取后 qApp->setStyleSheet 应用。

教学要点(QSS 最佳实践):
- 样式与逻辑彻底分离:设计师/非程序员可直接编辑 .qss,不必碰 C++;
- 开发期改 .qss 重跑即生效,不必改 C++ 重编译;
- 多主题物理分文件,编辑器对 .qss 有语法高亮。

README 同步更新差异表、最佳实践条目与目录结构。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 16:50:31 +08:00

4.4 KiB
Raw Blame History

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

对应教案 OUTLINE_4DAY.md Day3 下午「布局/控件 + QSS 美化」

  • ASSIGNMENTS.md Day3 下午作业。手工维护,非生成产物。

定位:上午版 + QSS 美化

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

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

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

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

QSS 最佳实践(本示例的刻意设计)

  1. 样式抽成外部 .qss 文件(而非硬编码 C++ 字符串):light.qss / dark.qss 是纯样式, 由 themes.qrc 编译进可执行文件,mainwindow.cppQFile 读取后 qApp->setStyleSheet 应用。好处:
    • 设计师/非程序员可直接编辑 .qss(不用碰 C++);
    • 开发期改 .qss 重跑即生效(不必改 C++ 重编译);
    • 多主题物理分文件,编辑器对 .qss 有语法高亮。
  2. ID 选择器认 objectNameQPushButton#btnEquals { ... } 命中的前提是控件 setObjectName("btnEquals")——本例 objectName 在 widget.ui 定义 <widget class="QPushButton" name="btnEquals">)。这是「样式写了没生效」头号原因 (忘设 objectName)的反面教材。
  3. 按键分色用功能归类DRY):数字键(btn0btn9,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

构建与运行

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 米黄背景 + 圆角)
  • 挑战版:深/浅双主题切换 ✓(视图菜单「深色主题」)