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

105 lines
5.7 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.
# QMainWindow 教学综合示例(qt_mainwindow_showcase
覆盖川大 wiki「5 QMainWindow」(pageId 58954529https://wiki.suncaper.net/display/scu2023/5+QMainWindow)
**5.15.6 全部六大核心组件**,形态为**极简文本编辑器**`QTextEdit` 中心部件),
纯组件演示、**无文件 I/O**。主窗体结构用 **Qt Designer`.ui`** 设计,应用图标与动作图标
**资源文件(`.qrc`**
> 仓库已有 `p03/ch05/` 的零散单组件示例(central_widget、dock_widget);本示例是
> **综合演示**,把六者整合到一个 `QMainWindow` 程序里,并能交互操控它们。
## 六大组件 ↔ 代码映射
| wiki | 组件 | 代码位置 | 演示的 API |
|---|---|---|---|
| 5.5 | 中心部件 | `mainwindow.ui``centralwidget/textEdit``.cpp``textChanged`/`cursorPositionChanged → updateStatusBar` | `setCentralWidget(QTextEdit)` |
| 5.1 | 菜单栏 | `.ui``menubar` + `menuFile/menuView/menuHelp/menuToolBarArea` + 12 个 `QAction``.cpp``on_action*_triggered/toggled` | `menuBar()`/`addMenu`/`QAction` |
| 5.2 | 工具栏 | `.ui``mainToolBar`(复用 `QAction`);`.cpp``setMovable`/`setAllowedAreas`/`setVisible` | `addToolBar`/`setAllowedAreas`/`setMovable` |
| 5.3 | 状态栏 | `.cpp``addPermanentWidget(statusPosLabel)`/`showMessage` | `addWidget`/`insertWidget`/`removeWidget`(见下) |
| 5.4 | 浮动窗口 | `.ui``dockWidget``.cpp``setFloating`/`setAllowedAreas` | `QDockWidget`/`addDockWidget` |
| 5.6 | 资源文件 | `mainwindow.qrc` + `.ui``windowIcon` + 各 `QAction` 图标 | `:/icons/*.png` |
## 关键设计点
### 1. QAction 是菜单项与工具按钮的公共抽象(5.1)
12 个 `QAction``.ui``MainWindow` widget 内**定义一次**,被菜单和工具栏**共同引用**
`<addaction name="..."/>`)——这正是 wiki 强调的「同一动作,加进菜单显示为菜单项、
加进工具栏显示为工具按钮」。例如 `actionNew` 同时出现在「文件」菜单和主工具栏。
### 2. 信号槽:on_\<objectName\>_\<signal\> 自动连接
槽命名遵循 Qt 约定,由 `setupUi()` 触发的 `QMetaObject::connectSlotsByName` **自动连接**
无需手写 `connect`KISS)。例如 `on_actionToggleDockFloating_triggered()` 自动连接
`actionToggleDockFloating``triggered` 信号。
### 3. 视图菜单 = 「操控」各组件的入口
| 动作 | 行为 | 对应组件/API |
|---|---|---|
| 显示主工具栏 ✓ | `mainToolBar->setVisible(checked)` | 5.2 |
| 显示状态栏 ✓ | `statusBar()->setVisible(checked)` | 5.3 |
| 工具栏可移动 ✓ | `mainToolBar->setMovable(checked)` | 5.2 `setMovable` |
| 停靠窗口浮动/停靠 | `dockWidget->setFloating(!isFloating())` | 5.4 `setFloating` |
| 显示浮动窗口 | `dockWidget->show()` | 5.4 重新显示(被 X 关闭后找回) |
| 关闭浮动窗口 | `dockWidget->hide()` | 5.4 直接隐藏 |
| 工具栏停靠区(子菜单 5 项) | `mainToolBar->setAllowedAreas(...)` | 5.2 `setAllowedAreas` |
### 4. 状态栏 API5.3
运行时演示 `addPermanentWidget`(永久「行:列 字数」标签)+ `showMessage`(动作临时提示)。
其余三 API 的等价用法(教学参考):
```cpp
// addWidget:在状态栏左侧添加普通部件(非永久,会挤占临时消息区)
statusBar()->addWidget(new QLabel("就绪"));
// insertWidget:在 index 位置插入部件
statusBar()->insertWidget(0, new QLabel("插入"));
// removeWidget:移除某部件
statusBar()->removeWidget(someLabel);
```
## 目录结构
```
mainwindow_showcase/
├── mainwindow.ui # Designer 表单:主窗体结构 + 12 个 QAction
├── mainwindow_showcase.h/.cpp # MainWindow 类(动态行为)
├── main.cpp # QApplication + offscreen 自动退出
├── mainwindow.qrc # 资源清单(5 个图标)
├── gen_icons.py # 图标生成脚本(标准库,无依赖)
├── icons/ # app/new/quit/about/dock.pnggen_icons.py 产物)
└── README.md # 本文档
```
## 构建与运行(Windows + MinGW 7.3.0 + Qt 5.14.2
> 必须用与 Qt 5.14.2 ABI 匹配的 mingw730_64`E:/Qt/Qt5.14.2/Tools/mingw730_64`),
> 不可用 PATH 中可能存在的更高版本 g++。
```bash
# 1) 生成图标
python docs/teaching/examples/mainwindow_showcase/gen_icons.py
# 2) 配置(在仓库根;本示例随 docs/teaching/examples 一起被顶层 CMakeLists 收录)
cmake -S . -B build_mw -G "MinGW Makefiles" \
-DCMAKE_PREFIX_PATH=E:/Qt/Qt5.14.2/5.14.2/mingw73_64 \
-DCMAKE_CXX_COMPILER=E:/Qt/Qt5.14.2/Tools/mingw730_64/bin/g++.exe \
-DCMAKE_C_COMPILER=E:/Qt/Qt5.14.2/Tools/mingw730_64/bin/gcc.exe
# 3) 构建单目标
cmake --build build_mw --target qt_mainwindow_showcase
# 4) 运行(GUI
PATH=/e/Qt/Qt5.14.2/5.14.2/mingw73_64/bin:$PATH \
QT_QPA_PLATFORM_PLUGIN_PATH=/e/Qt/Qt5.14.2/5.14.2/mingw73_64/plugins/platforms \
./build_mw/docs/teaching/examples/qt_mainwindow_showcase.exe
# 5) 离屏自动退出验证(退出码应为 0)
QT_QPA_PLATFORM=offscreen \
QT_QPA_PLATFORM_PLUGIN_PATH=/e/Qt/Qt5.14.2/5.14.2/mingw73_64/plugins/platforms \
PATH=/e/Qt/Qt5.14.2/5.14.2/mingw73_64/bin:$PATH \
./build_mw/docs/teaching/examples/qt_mainwindow_showcase.exe; echo "exit=$?"
```
## 教学要点小结
- 一个 `QMainWindow` = 菜单栏(≤1)+ 工具栏(多个)+ 状态栏(1)+ 浮动窗口(多个)+ 中心部件(1)。
- `QAction` 是「动作」的抽象,菜单与工具栏共享。
- 工具栏/浮动窗口都是**可移动**的,停靠区域可由 `setAllowedAreas` 限定。
- 资源文件(`.qrc`)把图标编译进可执行文件,运行时用 `:/...` 引用,无需关心磁盘文件。