- 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>
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(),③区自绘与②区QIconpixmap 共用(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 读它的真实几何:
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. 集成构建(仓库统一构建树)
# 配置(在仓库根)
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 工程)
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)。