Files
张宗平 05a685c952 Day3 教学示例:增强版计算器接入 + QMainWindow/QSS 两版参考实现
- calculator_designer_ext(Day2 增强版:表达式求值 + 括号,递归下降解析器)接入 cmake
- calculator_mainwindow(Day3 上午):增强版计算器装进 QMainWindow,
  菜单/状态栏/历史停靠窗,纯代码 + 显式 connect,与 mainwindow_showcase 形成坑卡对照
- calculator_mainwindow_qss(Day3 下午):上午版 + QSS 双主题美化(按键分色/伪状态/深浅切换)
- 验证 mainwindow_showcase(QMainWindow 六大组件综合演示,.ui + .qrc)
- OUTLINE_4DAY.md / ASSIGNMENTS.md Day3 衔接增强版起点 + 参考实现指引
- 补提交 Day2 calculator/ 与 calculator_designer/ 参考实现(CMakeLists 已引用)
- 全量构建 28/28,4 目标离屏自测退出码 0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:59:05 +08:00

9.4 KiB
Raw Permalink Blame History

Day2–4 课堂练习 + 课后作业(分层设计)

配套 OUTLINE_4DAY.md 的任务卡、slides/day2.htmlday4.html 里的「练/作业」小节。本文给出可直接打印/投屏的作业单:每项作业拆成 基础版(必做,验收线) + 挑战版(选做,见能力发挥) 两层,时间预算按 「基础版 1 小时内可完成、挑战版累计不超过 2 小时」控制,照顾基础不理想的 学员——先保基础版全员过关,挑战版不做不扣分

分层设计原则

  1. 基础版是及格线,不是引导线:题面本身已经是当天知识点的最小闭环,做完 基础版=当天目标达成;工程师答疑优先保基础版全员通过。
  2. 挑战版是同一个程序的自然延伸,不引入新知识点,只要求「更完整/更健壮/ 更贴近真实使用」——强度落在「把已学的东西用得更彻底」,不是提前预习明天内容。
  3. 验收用现场提问代替翻源码:给几组输入让学生当场演示结果(下表「验收用例」), 比对照代码更能测出是真理解还是照抄。
  4. 每天的作业首尾相接(计算器 → 计算器 QMainWindow 化 + 美化 → 数据存储工具), 挑战版做不完不影响第二天用基础版继续。

Day2 下午 · 简易计算器

对应任务卡 2OUTLINE_4DAY.md Day2 下午作业)。教师参考实现: examples/calculator/(代码布局版)、 examples/calculator_designer/Qt Designer 对照版)。

要求 时间预算
基础版(必做) 数字键 0–9 + 至少一种运算符(+/-/×/÷ 任选其一)+ 等号,能正确显示两个数的运算结果;界面不重叠、按钮可点击;connect 全部用新语法且写在构造函数里 ≈1h
挑战版(选做) 补全四则运算全部支持;小数点;清空键 C;退格键 ;除零不崩溃、显示 Error 且下一次输入自动清空;连续按运算符实现链式计算(如 2+3+4=9 累计 ≤2h

验收用例(现场让学生当场演示,不看代码):

  • 基础版:7 + 3 =109 - 4 =5(任选一种运算符即可)
  • 挑战版:6 ÷ 0 =Error4.5 + 0.5 =5;连续输入 12 后按退格 → 1 2 + 3 + 4 =9

给基础不理想同学的提示:卡在"点击没反应"先查 connect 有没有漏写、按钮有没有 真的加到布局里;卡在"数字显示不对"先只处理个位数,两位数以上的拼接逻辑 (display->text() + 新数字)留到基础版跑通个位数运算之后再加。


Day3 上午 · 计算器 QMainWindow 化

对应 OUTLINE_4DAY.md Day3 上午课堂练习(11:0012:00)。

参考实现:examples/calculator_mainwindow/ (以 Day2 增强版 calculator_designer_ext/ 为起点;CalculatorDesigner 是独立 QWidgetsetCentralWidget 装进 QMainWindow 核心求值逻辑不动,仅加 evaluated 信号供历史停靠窗订阅)。

要求 时间预算
基础版(必做) 把 Day2 计算器的键盘 setCentralWidget 装进 QMainWindow;加菜单栏「帮助→关于」,点击弹出 QMessageBox::about 显示一句自我介绍 ≈40min
挑战版(选做) 加一个「历史」停靠窗(QDockWidget + QListWidget):每次按等号,把这次的算式和结果(如 7+3=10)追加成一条历史记录;停靠窗可拖动/浮动/关闭(QDockWidget 默认行为,不用额外写代码) ≤1h

验收用例:点菜单「帮助→关于」能弹框;挑战版——连续算 3 次不同的算式,历史 停靠窗里能看到 3 条记录且内容正确。

给基础不理想同学的提示QMainWindow 不是 QWidget 的替代品,是新建一个 QMainWindow 子类,把原来计算器的键盘部分(QWidget 或其内容)通过 setCentralWidget() 塞进去;菜单点了没反应先检查 QAction 是不是忘了 connect (Day3 上午刚讲的坑卡)。挑战版做不完,历史停靠窗留空 QLabel 占位即可, 不影响 Day3 下午继续。


Day3 下午 · 计算器美化(QSS)

对应任务卡(OUTLINE_4DAY.md Day3 下午作业)。

参考实现:examples/calculator_mainwindow_qss/ Day3 上午版 + QSS 双主题;与上午版仅 mainwindow.{h,cpp} 差异,演示「美化与逻辑正交」)。

要求 时间预算
基础版(必做) 数字键 / 运算键 / 等号键至少用 3 种不同颜色区分(setObjectName + QSS ID 选择器 #objectName{...});整体布局随窗口缩放不重叠、不错位 ≈1h
挑战版(选做) 至少 1 个按钮有 :hover:pressed 视觉反馈;给结果显示框也套样式(圆角边框/字号);额外做一个"深色主题"QSS 字符串,加一个按钮或菜单项用 setStyleSheet() 在两套样式间切换 ≤1h

验收用例:缩放窗口到很小和很大两种尺寸,按钮不重叠不错位;挑战版——点切换 主题按钮,界面颜色整体改变。

给基础不理想同学的提示QSS 选择器认的是 objectNamesetObjectName("btnEquals") 之后才能用 #btnEquals{...}),忘设置 objectName 是"样式写了但没生效"的头号原因; 先做好 1 种颜色区分再扩展到 3 种,不要一次性套一大段 QSS 上去调不出问题在哪。


Day4 上午 · 事件过滤器 / 自定义绘图

对应 OUTLINE_4DAY.md Day4 上午课堂练习(11:0012:00)。

要求 时间预算
基础版(必做,二选一) ① 给某个控件装 installEventFilter(),鼠标按下时在控制台打印坐标; ② 重写 paintEvent,用 QPainter 画一个组合图形(棋盘格、简单进度条、或几条交叉线均可) ≈40min
挑战版(选做,两项整合) 在一个自定义 QWidget 上:鼠标点击时记录点击坐标(mousePressEvent 或事件过滤器都行)到一个 QVector<QPoint>,每次点击后 update() 触发重绘,paintEvent 里把历史上所有点击过的坐标都画出来(比如画小圆点)——点越点越多,图案累积不丢失 ≤1h

验收用例:基础版①——点击窗口能在控制台看到坐标打印;基础版②——窗口能看到 一个图形;挑战版——连续点击 5 个不同位置,5 个点都保留在画面上(不是只显示 最后一个)。

给基础不理想同学的提示:基础版明确「二选一」,不要求两项都做——事件拦截和 自定义绘图是两条独立线索,先吃透一条。忘调用 update() 是"画了但界面没刷新" 的头号原因(paintEvent 只在 Qt 认为需要重绘时才会被调用,手动改了数据必须 自己触发 update())。


Day4 下午 · 本地数据存储小工具

对应任务卡(OUTLINE_4DAY.md Day4 下午作业)。这是 Day5 综合案例 examples/student_manager/ 的直接前身, 教师验收时可参考其数据层设计(不要求学生做到那个完整度)。

要求 时间预算
基础版(必做) 「学员信息」表单(姓名/成绩/标签,3 个 QLineEdit + 「添加」按钮)把记录追加到列表控件(QListWidget/QTableWidget 均可);「保存」按钮把全部记录写成 JSON 文件;重启程序后「读取」按钮能把之前保存的记录读回、字段不丢、顺序不乱(至少 2 条) ≈1.5h
挑战版(选做) ① 加「删除选中行」;② 数据文件路径用 QCoreApplication::applicationDirPath() 拼接,不用裸相对路径(当天★坑卡的实操版);③ 读取时文件不存在/JSON 格式损坏要给出友好提示而不是崩溃或静默清空(检查 open() 返回值和 QJsonParseError ≤1h

验收用例:添加 2 条记录 → 保存 → 关闭程序 → 重新打开 → 点「读取」→ 2 条记录 都在、字段值正确;挑战版——把 JSON 文件手动改坏一个字符再读取,程序不崩溃。

给基础不理想同学的提示:先固定用一个写死的文件名(比如 data.json)把 「写入→读回」跑通,再考虑路径是否规范(挑战版①);QJsonDocument::toJson()/ fromJson() 是配对的两端,写的时候用什么结构(数组套对象),读的时候就按同样 结构解析回来,两边字段名要完全一致(区分大小写)。


给工程师/助教的验收操作提示

  • 11:0012:00、16:0017:00 两个答疑窗口,优先确认基础版验收用例,挑战版 时间不够可以留到当晚或第二天早上补交,不阻塞后续课程进度。
  • 每天验收合格线 = 基础版全部用例通过;挑战版按完成比例加分,不设满分门槛。
  • 若某学员基础版都吃力,参照各节「给基础不理想同学的提示」拆解成更小步骤, 必要时可对照教师参考实现(examples/calculator/examples/calculator_designer/ 逐段讲解,但不要直接给学生抄源码——抄一次治标不治本,下一天同类问题会 重复出现。