Day4 教学示例补三个:QDialog 综合 / QLineEdit 小眼睛 / 文件 IO(+顶层构建注册)
- qdialog_showcase:wiki「6 对话框 QDialog」6.2–6.5 综合演示。含两套实现:
· Designer 表单版(dialog.{h,cpp,ui} + resources.qrc + source.gif,QMovie 播 GIF)
· 纯代码版(qt_dialog_showcase.cpp,单文件,QWidget 布满按钮逐个演示 QDialog 行为)
- lineedit_eye_toggle:子类化 QLineEdit,paintEvent 自绘小眼睛、mouseEvent 命中切换
echoMode,并与内置 clear button 动态避让(读 objectName=="clearButton" 子 widget 几何)。
含独立子目录 CMakeLists.txt 供单独打开(顶层 add_subdirectory 不递归)。
- file_io_demo:QFile/QTextStream/QDataStream/QFileInfo/QDir/QTextCodec/QJson 五主题
综合示例,每个按钮产出一个文件落到 demo_output/ 便于课堂手动查看。
构建注册:examples/CMakeLists.txt 用 add_teaching_example 注册前两个纯代码示例,
mandelbrot 多源文件单独 add_executable;calculator_mainwindow_qss 加 themes.qrc 与
AUTORCC;all_teaching_examples 依赖列表同步补齐。
附 lineedit_eye_toggle 设计文档(docs/superpowers/specs)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# QLineEdit 自绘小眼睛 / echo mode 切换(qt_lineedit_eye_toggle)
|
||||
|
||||
Day4 上午教学示例(OUTLINE_4DAY.md Day4 上午「消息机制和事件 + 绘图事件」),**同时覆盖两个主题**:
|
||||
|
||||
- **组件绘制**——覆写 `paintEvent`,用 QPainter 在 QLineEdit 右侧自绘眼睛图标;
|
||||
- **事件捕捉**——覆写 `mousePressEvent` / `mouseMoveEvent`,几何 hit-test 命中眼睛时切换
|
||||
`echoMode`,且不阻断基类的光标定位 / 拖选。
|
||||
|
||||
载体是 QLineEdit 密码框:右侧一个自绘小眼睛,点击在 `Password` ↔ `Normal` 间切换,并显式
|
||||
处理与 QLineEdit 内置 clear button 的位置冲突。
|
||||
|
||||
## 三区对照(先简后深)
|
||||
|
||||
| 区 | 内容 | 教学作用 |
|
||||
|---|---|---|
|
||||
| ① echo mode 四态 | Normal / NoEcho / Password / PasswordEchoOnEdit 静态对照 | 先给 echo mode 全貌,眼睛只是切换载体 |
|
||||
| ② addAction 一行版 | `addAction(QIcon, TrailingPosition)` 加眼睛,点击切换 | Qt 内置、1 行实现——「为什么还要自绘」的引子 |
|
||||
| ③ 自绘版主秀 | `PasswordLineEdit` 自绘眼睛 + 「启用 clear button」复选框 | 主题落地 + clear button 避让 |
|
||||
|
||||
## 关键教学点
|
||||
|
||||
### 1. 组件绘制
|
||||
- `paintEvent` **先调基类**画原生内容(文本 / 边框 / clear button),再用 QPainter 叠加眼睛。
|
||||
顺序不能反——基类画完后 clear button 几何才最终确定,眼睛避让才准。
|
||||
- 眼睛用 QPainter 纯代码绘制(眼眶椭圆 + 瞳孔 / 斜杠两态),无外部资源。绘制逻辑抽成自由函数
|
||||
`paintEye()`,③区自绘与②区 `QIcon` pixmap 共用(DRY,且对照更直观)。
|
||||
|
||||
### 2. 事件捕捉
|
||||
- `mousePressEvent`:命中眼睛矩形 → 切 `echoMode` + `e->accept()` + `return`(**不**调基类,
|
||||
否则 QLineEdit 把这次点击当光标定位);非命中 → 调基类(光标定位 / 双击选词 / 右键菜单照常)。
|
||||
这是「自绘交互区与原生编辑行为共存」的核心。
|
||||
- `mouseMoveEvent` + `setMouseTracking(true)`:实现 hover 高亮。**坑卡**:`mouseTracking` 默认关,
|
||||
不按鼠标键就收不到 `mouseMoveEvent`,hover 高亮出不来。
|
||||
|
||||
### 3. clear button 避让(读 clearButton 子 widget 几何)
|
||||
QLineEdit 内置 clear button 的宽度随主题 / DPI / 字号变化,**不能硬编码偏移**(硬编码是反面教材,
|
||||
换主题即错位)。正确做法:clear button 是 QLineEdit 的一个 `objectName=="clearButton"` 直接子 widget
|
||||
(Qt5 私有 `QLineEditIconButton`),用 `findChild` 读它的真实几何:
|
||||
|
||||
```cpp
|
||||
if (QWidget* cb = findChild<QWidget*>(QStringLiteral("clearButton"),
|
||||
Qt::FindDirectChildrenOnly)) {
|
||||
rightEdge = cb->x() - 4; // 眼睛贴 clear button 左侧,留 4px 缝
|
||||
}
|
||||
```
|
||||
|
||||
眼睛紧贴其左侧;未启用 clear button 或无文本(clear button 不占位)时贴右边。勾选③区复选框即可实时
|
||||
观察眼睛从「贴右」移到「贴 clear button 左侧」、两者不重叠。
|
||||
|
||||
> 为什么不用 `QStyle::subControlRect`?QLineEdit 不经 QStyle 的 complex-control 绘制,
|
||||
> `QStyle` 没有 `CC_LineEdit` / `SC_LineEditClearButton`,无对应 subcontrol 可查——读子 widget 是唯一可靠途径。
|
||||
|
||||
## 目录结构
|
||||
```
|
||||
lineedit_eye_toggle/
|
||||
├── qt_lineedit_eye_toggle.cpp # 唯一源文件(paintEye + PasswordLineEdit + ShowcaseWidget + main)
|
||||
├── CMakeLists.txt # 独立顶层工程(可单独 cmake -S . -B build,不走仓库统一构建)
|
||||
└── README.md # 本文档
|
||||
```
|
||||
|
||||
## 构建与运行(Windows + MinGW 7.3.0 + Qt 5.14.2)
|
||||
|
||||
> 必须用与 Qt 5.14.2 ABI 匹配的 mingw730_64,不可用 PATH 中更高版本的 g++。
|
||||
|
||||
### A. 集成构建(仓库统一构建树)
|
||||
```bash
|
||||
# 配置(在仓库根)
|
||||
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
|
||||
|
||||
cmake --build build_mw --target qt_lineedit_eye_toggle
|
||||
|
||||
# 运行(GUI,点 ②③ 的眼睛、勾选 clear button 体验)
|
||||
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_lineedit_eye_toggle.exe
|
||||
|
||||
# 离屏自动退出验证(不交互,退出码应为 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_lineedit_eye_toggle.exe; echo "exit=$?"
|
||||
```
|
||||
|
||||
### B. 独立构建(单独 cmake 工程)
|
||||
```bash
|
||||
cd docs/teaching/examples/lineedit_eye_toggle
|
||||
cmake -S . -B build -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
|
||||
cmake --build build
|
||||
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/qt_lineedit_eye_toggle.exe
|
||||
```
|
||||
|
||||
> 两条路径编译同一份 `qt_lineedit_eye_toggle.cpp`,行为一致。集成路径进入仓库统一构建;
|
||||
> 独立路径可把这个目录单独拷走即用(仅需本目录三文件 + 一个 Qt 5.14.x)。
|
||||
Reference in New Issue
Block a user