正常
卡住怎么办
← 手册首页
按症状查。每条给方向,不给整段答案——成品 repo 在 widget/ip-edit/,对照着看。
cpp 编译报 invalid use of incomplete type 'class AwesomeQt::QLabel'(new QLabel 那行)
- 头文件里是不是写了
namespace AwesomeQt { class QLabel; }前向声明?编译器会把QLabel当成AwesomeQt命名空间内的类,和全局::QLabel不是同一类型,cpp 里new QLabel时类型不完整。→ 删掉命名空间内的前向声明,头文件顶部直接#include <QLabel>(QLabel 是非模板 Qt 公有类,include 安全):include/ip_edit.h:8 - 同理检查
QLineEdit也别前向声明——它一样要直接 include:include/ip_edit.h:9 - 进阶排查:QLabel / QLineEdit
cpp 编译报 'senderIndex' was not declared in this scope
- 是不是在
onOctetTextChanged槽里调了senderIndex()想取发送者段索引?那函数压根没定义。→ 改在connect(textEdited, ...)的 lambda 里按值捕获段索引i,满位判断内联进 lambda,删掉槽声明与定义:src/ip_edit.cpp:37 - 别用
sender()反查再qobject_cast——构造循环里捕获i干净得多,也避免运行时类型转换 - 进阶排查:信号与槽
按 . 跳下段后,下一段里冒出一个多余的 .
keyPressEvent的Key_Period分支是不是只focusNextOctet(current)没event->accept()?没 accept 事件继续冒泡,子QLineEdit默认处理把点号当字符输入。→ 跳段后event->accept()消费掉点号:src/ip_edit.cpp:220- 检查
Key_Comma(兼容小键盘/中文输入习惯)分支也 accept 了:src/ip_edit.cpp:216 - 进阶排查:QKeyEvent
调一次 setText 外部接到 4 次 textChanged(回显闪好几次)
setText循环里每段edit->setText()是不是没屏蔽信号?每段触发子段textChanged、step 1 那条转发 lambda 各 emit 一次整体地址,4 段就 4 次假通知(中间还是半成品地址)。→ 每段回填前包QSignalBlocker blocker(edit)(RAII 出作用域自动恢复),循环结束后统一emit textChanged(text())一次:src/ip_edit.cpp:104/src/ip_edit.cpp:117clear()同样要屏蔽,否则清 4 段也发 4 次:src/ip_edit.cpp:155- 进阶排查:QSignalBlocker
段首退格跳不回上段,或跳回了却删错位
- 三个条件是不是漏了一个?必须同时满足
edit->text().isEmpty()(段空)+edit->cursorPosition() == 0(光标在段首)+current > 0(非首段)才跳。漏判「段空」会导致段里有字也被跳走。→src/ip_edit.cpp:233 - 跳回上段后是不是没把光标置段末?
prev->setCursorPosition(prev->text().length())把光标移到段末,prev->backspace()才能删掉末位。不置段末,backspace()删的位置不对。→src/ip_edit.cpp:237 - 进阶排查:QLineEdit::backspace
Tab 进控件后 4 段全不亮,得再按一次 Tab 才进第一段
- 壳
QWidget没设焦点代理,Tab 聚焦到壳本身而非子段。→ 构造末尾setFocusProxy(octets_[0])+setFocusPolicy(Qt::StrongFocus):src/ip_edit.cpp:69 - 检查
octets_[0]在setFocusProxy调用时已经建好了(在构造循环之后调):src/ip_edit.cpp:28的循环跑完才有octets_[0] - 进阶排查:QWidget::setFocusProxy
子段里能敲进字母(以为校验失效)
- 每段是不是漏挂
QIntValidator?挂上后非数字根本敲不进。→ 构造里edit->setValidator(new QIntValidator(0, 255, this)):src/ip_edit.cpp:26(4 段共用同一个 validator,循环外建一次) - 注意:
QIntValidator只在用户键盘输入时拦截;程序化setText("abc")它拦不住,得靠setText内部toInt失败补 0 兜底。→src/ip_edit.cpp:108 - 进阶排查:QIntValidator
setText("999.1.1.1") 显示成 999.1.1.1(越界没夹)
setText循环里是不是漏了std::clamp(val, 0, 255)?→ 每段取值后val = std::clamp(val, 0, 255):src/ip_edit.cpp:111- 别忘了 cpp 顶部
#include <algorithm>,否则std::clamp未声明:src/ip_edit.cpp:9 - 缺段(如
"1.2.3")补 0 也别漏:i >= parts.size()分支edit->setText("0"):src/ip_edit.cpp:114
moc 报错(Q_PROPERTY 不认识)
- 类里有没有
Q_OBJECT?IpEdit 有 Q_PROPERTY,漏了 moc 不生成元对象。→include/ip_edit.h:23 - CMake 有没有开 AUTOMOC(
set(CMAKE_AUTOMOC ON))?→widget/CMakeLists.txt - Q_PROPERTY 的
placeholderHint三件套(READ/WRITE/NOTIFY)是不是齐全且名字一致?→include/ip_edit.h:26 - 进阶排查:QObject 与元对象系统