26 KiB
Scene 及相关模块 BUG/逻辑排查报告
排查范围:
scene/目录全部代码 +testprintwidget.cpp/.h+mainwidget.cpp/.h+InkJetPrinter.cpp/.h排查目标:找出可能导致程序崩溃、内存泄漏、悬空指针、UI 异常等隐患
本次只输出排查结果与解决方案,不修改代码
一、排查思路
针对桌面 Qt + QGraphicsScene 框架下打印机控制软件这一类典型的「长生命周期 + 多线程 + 多对话框 + 共享场景」程序,我按以下维度系统性地审查代码:
-
空指针/悬空指针
scene()/parent()/focusItem()/selectedItems()在 item 未入场或已删除时是否被解引用dynamic_cast<>失败后是否仍当成有效指针使用- 槽函数捕获的裸指针 item 在异步触发时是否已销毁
-
生命周期/所有权
new出来的子 widget、QGraphicsScene、QThread、Serial、Timer 是否有 parent,析构是否释放m_pSavePicScene = new QGraphicsScene()这类无 parent 的对象- 子线程退出顺序与
moveToThread的对象delete时机 - 「编辑器对话框」持有的
item*在 item 被场景删除后未置空
-
类型与边界
QImage创建尺寸可能为 0/负数- 像素读写、
scanLine、copy()越界 QVector/QList索引越界(m_currCounterValues[1]等)QVariant类型不匹配强转(toString/toMap)
-
重入与状态机
setSource()→applyModify()→update()是否产生递归itemChange()返回值不正确导致几何更新无限触发- 信号-槽链中是否互发导致死循环
-
资源未清理
- 析构里漏掉
timer->stop()、thread->quit()、disconnect()、子 widget delete connect未配disconnect,导致已删除对象的回调被触发
- 析构里漏掉
-
UI 与 IO 健壮性
- 文件路径不存在、XML 不合法、字体不存在、图片加载失败时的回退
- 用户操作(双击、空选中、未填字段)下的边界路径
排查方式:逐文件 read + 关键字交叉 grep(scene(), selectedItems(), dynamic_cast, delete , new , connect(, qDebug, assert 等),并对 InkJetPrinter / TestPrintWidget / MainWidget / 各 Item 类的关键流程绘制调用链。
二、排查结果总览
| 模块 | 高风险 | 中风险 | 低风险 | 合计 |
|---|---|---|---|---|
| scene 目录 Item 类(pictextitem / piccodeitem / PicImageItem 等) | 5 | 5 | 2 | 12 |
| scene 目录 编辑器/视图(picscene / myview / 各 Editor) | 3 | 4 | 1 | 8 |
| testprintwidget | 4 | 4 | 1 | 9 |
| mainwidget | 3 | 3 | 1 | 7 |
| InkJetPrinter | 4 | 4 | 1 | 9 |
| 合计 | 19 | 20 | 6 | 45 |
说明:以下问题中带 ⚠️ 标志的为已经较为确定可触发崩溃;其余为基于代码模式判断的潜在隐患。
三、scene/ 目录下 Item 类相关问题
3.1 ⚠️【高】pictextitem.cpp:441-442 clampItemPos 未判空 scene()
QPointF PicTextItem::clampItemPos(const QPointF &p)
{
return QPointF (std::min(qreal(scene()->width() - boundingRect().width()), std::max(0.0, p.x())),
std::min(qreal(scene()->height() - boundingRect().height()), std::max(0.0, p.y())));
}
问题:item 尚未 addItem 到 scene、或粘贴/克隆时短暂离开 scene 时调用此函数,scene() 返回 nullptr,直接解引用即崩。
复现:复制粘贴 item、或在删除瞬间触发 mouseRelease/keyPress。
修复方案:
auto* sc = scene();
if (!sc) return p;
qreal w = sc->width() - boundingRect().width();
qreal h = sc->height() - boundingRect().height();
return { std::min(w, std::max(0.0, p.x())), std::min(h, std::max(0.0, p.y())) };
澄清 已修复
3.2 ⚠️【高】pictextitem.cpp:346 / 352 / 375-377 mouseReleaseEvent & keyPressEvent 未判空 scene()
两处均直接 scene()->update() 与 scene()->selectedItems(),与 3.1 同样在 item 离场时崩溃。
修复方案:进入函数先 if(!scene()){ ... ::xxxEvent(event); return; }。
3.3 ⚠️【高】pictextitem.cpp:415-432 strToImage 可能创建 0 宽/0 高 QImage
QImage img(fm.horizontalAdvance(str), fm.height(), QImage::Format_ARGB32);
问题:str 为空、或字符全部为不可打印字符时,horizontalAdvance 返回 0,QImage(0, h, ...) 是无效图像,后续 img.fill / img.rect / clipImage 中循环按 width=0 跳过,但 fm.height() 也可能因字体加载失败为 0;最终 clipImage 内可能跳到 end: 直接 img.copy(QRect()) 返回空。再走 applyImgeTranslation 中 scaled 到 0 宽,下游 paint 用空 QImage 仍可工作,但 boundingRect 变为 (0,0,0,0),被选中后 drawRect(r) 画零矩形,并不至于 crash,但 fm.horizontalAdvance 在某些极端字符串/字体下,QFontMetrics 实现里有 [QTBUG] 历史已知崩溃记录。
修复方案:
int w = std::max(1, fm.horizontalAdvance(str));
int h = std::max(1, fm.height());
QImage img(w, h, QImage::Format_ARGB32);
澄清 已修复
3.4 ⚠️【高】pictextitem.cpp:304-316 itemChange() 修改 newPos 后未返回
QVariant PicTextItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemSceneChange && scene()) {
QPointF newPos = value.toPoint();
QRectF rect = scene()->sceneRect();
if (!rect.contains(newPos)) {
newPos.setX(...); newPos.setY(...);
}
}
return QGraphicsItem::itemChange(change, value); // <- 返回原值
}
问题:
change变量名错了:clamp 应该用ItemPositionChange,而代码写的是ItemSceneChange,逻辑根本没生效;- clamp 后
newPos没有 return,等于做了无用功。
风险:item 可被拖出 scene;与mouseReleaseEvent中的 clamp 配合时位置异常,并非崩溃但是逻辑 BUG。
修复方案:
if (change == ItemPositionChange && scene()) {
QPointF newPos = value.toPointF();
QRectF rect = scene()->sceneRect();
if (!rect.contains(newPos)) {
newPos.setX(qBound(rect.left(), newPos.x(), rect.right()));
newPos.setY(qBound(rect.top(), newPos.y(), rect.bottom()));
}
return newPos;
}
return QGraphicsItem::itemChange(change, value);
注:此处还把 value.toPoint() 写成了整型 Point,丢精度,应改 toPointF()。
澄清
该段代码使用已久,未发现异常。暂不修复
3.5 ⚠️【高】piccodeitem.cpp:73 m_currCounterValues 索引可能越界
auto txt = generateTxtFromBarcodeViewModel(m_vm, {m_currCounterValues[0], m_currCounterValues[1]}, ...);
问题:构造函数初始化 m_currCounterValues({0, 0})(size=2 OK),但 updateVariants(const QVector<int>) 入参 counters 直接赋值 m_currCounterValues = counters。一旦上层只传 1 个或空 vector,[0]/[1] 越界。
修复方案:
int c0 = m_currCounterValues.size() > 0 ? m_currCounterValues[0] : 0;
int c1 = m_currCounterValues.size() > 1 ? m_currCounterValues[1] : 0;
auto txt = generateTxtFromBarcodeViewModel(m_vm, {c0, c1}, QDateTime::currentDateTime());
或在 updateVariants(const QVector<int>) 入口校验/补齐为 size=2。
澄清
已经在updateVariants入口处校验size
3.6【中】piccodeitem.cpp:31-34 setSource 直接忽略入参
void PicCodeItem::setSource(QVariant var) { applyModify(); }
问题:参数 var 未使用,但调用者通常假设 setSource(text) 会更新文本;该类把数据来源换成了 m_vm。
风险:被 setCustomFont 之类重新调用时可能逻辑错乱,但不会崩。
修复方案:用 Q_UNUSED(var); 显式声明,或将公共抽象上提。
澄清: source/setSouce 机制准备弃用,不与修复
3.7【高/中】pictextitem.cpp:153 setBoldMultiple 缺少返回值
int PicTextItem::setBoldMultiple(int multiple) { m_boldMultiple = multiple; }
问题:声明返回 int 却没有 return,未定义行为;GCC/MSVC 优化下可能取到栈垃圾。如果调用方使用了返回值,可能挂掉。
修复方案:返回类型改为 void,或 return multiple;。
澄清: 已修复
3.8【高】PicImageItem.cpp:16-18 图片加载失败仍使用旧/空对象
QImage img(var.toString());
if (img.isNull()) return;
m_img = img;
若加载失败,m_img 仍然是旧值(可能未初始化)。后续 boundingRect / paint 仍按之前尺寸绘制可能不一致;如果是首次加载失败,m_img 默认构造的空 QImage 会让 boundingRect 为 0 区域,后续 applyImgeTranslation 中 scaled 到 0 宽,与 3.3 同样存在风险。
修复方案:
if (img.isNull()) { m_img = emptyImage(); applyModify(); return; }
澄清: 已修复
3.9【高】PicScheduleShiftItem.cpp:98 返回临时对象引用导致悬空
(来自子代理报告,已确认)
修复方案:函数返回值改为按值或返回成员引用。
澄清: 已修复
3.10【中】pictextitem.cpp:24-25 文档对象 stylesheet 在 delete document() 后失效
document()->setDefaultStyleSheet(...) 是合法的,但 setSource 后我们用的是 strToImage 自绘的 QImage,与 QGraphicsTextItem 内部 QTextDocument 的内容可能不一致。
风险:若上层 paint 走 fallback 分支(SourceType::UNKNOWN)调用 QGraphicsTextItem::paint,会绘制空文档;但属于显示瑕疵不至于崩。
修复方案:在 setSource 同时也 setPlainText(str),或在 fallback 中显式 setPlainText。
澄清: 全面自绘,不与修复
3.11【中】piccodeitem.cpp:14-19 lambda 捕获 this 但 m_dateVarTimer 父对象为 nullptr
QTimer m_dateVarTimer 是 PicCodeItem 的成员变量,但 PicCodeItem 不继承 QObject(继承 QGraphicsTextItem),析构时对 lambda this 指向已开始析构的对象。当前构造时未 start,看似无害,但若有人启用 m_dateVarTimer.start(...),析构里 m_dateVarTimer.stop() 后仍可能正在派发的事件循环里持有 lambda → 崩。
修复方案:在析构前 m_dateVarTimer.disconnect(); m_dateVarTimer.stop();。
3.12【低】pictextitem.cpp:41-87 clipImage 使用 goto + originRect 变量未使用
代码可读性差,未使用的 originRect
澄清: 不予修复
四、scene/ 编辑器/视图相关问题
4.1 ⚠️【高】picscene onFocusItemChanged 持有 currFocusItem 裸指针
当前 currFocusItem 在 item 被 scene 删除后没有被清空(场景层未 connect QGraphicsScene::changed 或 QObject::destroyed)。
复现:聚焦一个 item,再点击删除按钮,再做依赖 currFocusItem 的操作(如 Ctrl+B 加粗、键盘移动)。
修复方案:在 removeItem 前后显式清空 currFocusItem,并在 onFocusItemChanged 之外用一个专门的「current 选中」并通过 connect(scene, &QGraphicsScene::selectionChanged, ...) 单一来源,避免栈悬空。
4.2 ⚠️【高】BarcodeEditor / DlgBarcodeFormat / DlgQrcodeFormat 等编辑器持有 PicCodeItem* 后,item 可能被场景删除
testprintwidget.cpp 中 codeItem_Operation 长期持有 item 指针;编辑器(modal/non-modal 不一)打开后用户在外部做了「全部删除」或加载新模板,原 item 已 removeItem + delete,编辑器返回时 codeItem_Operation->setBarcodeViewModel(...) → 崩。
修复方案:
- 编辑期间禁用其他可能删除 item 的按钮;或
- 用
QPointer<PicCodeItem>持有,使用前判空;或 - 在
removeItem前发信号通知所有打开的编辑器关闭。
4.3【中】myview / sceneviewwidget setSceneRect / centerOn 在 scene 未就绪时调用
若 bindPicScene(nullptr),后续视图操作崩。
修复方案:所有调用前 if(!scene()) return;。
4.4【中】ItemEditor / ItemGeneralSettings 信号槽传 raw PicTextItem*
信号槽走 Qt::QueuedConnection 时 item 已释放则崩。
修复方案:参数改 QPointer<PicTextItem>,或改成传 id(item->data(0) 存 uuid),槽内查表。
4.5【中】ScheduleShiftsEditor 处理 item 删除后再编辑
当用户删除当前编辑的 ScheduleShift item 后,再次双击 / 接收编辑信号,会用陈旧指针访问。
修复方案:在 picscene 的 itemRemoved 中关闭对应编辑器。
4.6【中】各对话框 BarcodeEditor m_barcodeEditor;(栈/成员对象)
- 与场景 item 的关联在多次打开时未 reset;
exec()嵌套时事件循环重入。
修复方案:每次进入exec()前清状态;嵌套场景禁用相关按钮。
4.7【中】ImageLoader 模态弹出与 item 创建顺序
若用户取消选择,但仍走「创建 item」分支,会插入空图像 item(与 3.8 联动)。
修复方案:取消则不 addItem。
4.8【低】ViewModels.cpp BarcodeViewModel::loadFromXml 默认值
若 XML 无相应字段,需要 fallback 到默认 type/format,避免崩在下游 generateBarcodeImage。
五、testprintwidget 相关问题
5.1 ⚠️【高】testprintwidget.cpp:55 / .h:175 m_pSavePicScene = new QGraphicsScene() 无 parent 且析构未释放
风险:每次打开/关闭测试打印窗口都会泄漏一个 QGraphicsScene 及其 items。
修复方案:new QGraphicsScene(this),并把它置 nullptr 后再 delete 以避免析构里 item 重复释放冲突。
5.2 ⚠️【高】testprintwidget.cpp:1077-1092 / 1461-1477 codeItem_Operation 删除后未置空(与 4.2 联动)
修复方案:on_delButton_pressed / 「全部删除」中 codeItem_Operation = nullptr;,使用前 QPointer + 判空。
5.3 ⚠️【高】testprintwidget 多处 selectedItems() 不判空 + 强转
foreach (QGraphicsItem* it, scene->selectedItems()) {
PicTextItem* p = (PicTextItem*)it; // C 风格转换
p->setSource(...); // 若 it 不是 PicTextItem 则崩
}
修复方案:auto* p = qgraphicsitem_cast<PicTextItem*>(it); if(!p) continue;。
5.4 ⚠️【高】构造函数中 m_TextEdit 在第 64 行才 new,但第 48-52 行已构造对话框
若对话框构造里访问 getQTextEdit() → 段错误。
修复方案:把 m_TextEdit = new QTextEdit(0); 上移到第一个 dialog 之前。
5.5【中】复制/粘贴 attrs (m_copiedAttrs) 反复 set/get
QXmlStreamAttributes不持有字符串数据所有权,浅引用QStringRef在原 QString 释放后悬空。- 推荐
QMap<QString,QString>取代。
5.6【中】onFileOpen / parseVbfile 健壮性
- 文件不存在、非 UTF-8、不合法 XML 都需要回退;
m_TextEdit->document()->toHtml()与场景 item 同步顺序。- 当前缺少
if (!file.open(...)) return;与最后file.close()。
5.7【中】saveFile / onSaveASFile 路径含中文/无写权限
- 应使用
QSaveFile防止崩盘截断。 QFileDialog::getSaveFileName的过滤器要严格。
5.8【中】eventFilter 对象判断
if (obj == m_TextEdit) { ... } else if (obj == ...) { ... }
return QWidget::eventFilter(obj, ev);
当 m_TextEdit 还未 new、或上一句中 widget 已被 deleteLater 时 obj 比较是裸指针比较,只要严格判空 obj 不会崩,但中间可能漏处理。
5.9【低】析构里 item 销毁顺序
pPicScene 是 new PicScene(this) 有 parent,正常 Qt 自动释放;但 m_pSavePicScene 不是(与 5.1)。
六、mainwidget 相关问题
mainwidget.cpp/.h 由于篇幅与上下文限制本次未全文阅读,下列基于 search 与已知调用链推断,标注为「待复核」。
6.1 ⚠️【高·待复核】onPreviewScene / handleEmptySize:当 pPicScene 为空 or items().isEmpty() 时直接走绘制路径
风险:未判空 → 段错误。
修复方案:进入函数顶部 if(!pPicScene || pPicScene->items().isEmpty()) return;。
6.2 ⚠️【高·待复核】imageToPrintData / SendPrintDataToFpga 像素读写越界
- 若上游 QImage 宽高与 FPGA 协议假设的
width=128/256/512, dot=7/9不一致,scanLine(y)+x会越界。 bytesPerLine()与width()/8不一定相等(行对齐)。
修复方案:使用img.bits()时严格按bytesPerLine()走,且校验img.format()是否为期望格式(必要时img = img.convertToFormat(QImage::Format_Mono))。
6.3 ⚠️【高·待复核】timerShowItem / timerPowerOff / airPushTimer 析构未停
风险:定时器仍在排队 timeout,对象析构后 lambda 触发崩溃。
修复方案:析构里逐一 stop() 并 disconnect()。
6.4【中·待复核】generateCharRamData 字符不在字体表
glyph索引超出范围崩;
修复方案:fallback 到默认占位 glyph。
6.5【中·待复核】bindPicScene(scene*) 后被外部析构
当 testprintwidget 退出后,被 mainwidget 持有的同一 PicScene* 失效。
修复方案:所有权要明确:要么 mainwidget 创建并独占;要么 PicScene 多线持有用 shared_ptr 或 QPointer。
6.6【中·待复核】m_setNumDlg / m_fileManageWidget 懒加载重复 new
修复方案:if(!m_xxx) m_xxx = new ...(this);。
6.7【低·待复核】updateSysStatusToUI 索引/越界
- 状态枚举数组按 index 取 label 时需要
qBound。
七、InkJetPrinter 相关问题
7.1 ⚠️【高】析构线程未安全清理 Serial(46-60)
serialFPGA / serialSTM32 已 moveToThread,先 quit/wait 线程后再 delete 这两个对象,存在跨线程释放和待派事件冲突。
修复方案:
~InkJetPrinter() {
if (serialFPGA) { serialFPGA->disconnect(); serialFPGA->deleteLater(); }
if (serialSTM32){ serialSTM32->disconnect(); serialSTM32->deleteLater(); }
if (m_serialThreadFPGA && m_serialThreadFPGA->isRunning()) { m_serialThreadFPGA->quit(); m_serialThreadFPGA->wait(3000); }
if (m_serialThreadSTM32 && m_serialThreadSTM32->isRunning()) { m_serialThreadSTM32->quit(); m_serialThreadSTM32->wait(3000); }
// 不要再 delete serialFPGA/serialSTM32
}
7.2 ⚠️【高】析构未停 timer / 未清子 widget
m_Timer / timer / viscosity_timer / jd_timer / m_MainWidget / m_TestPrintWidget / m_BarCodeDlg / ... 都是 new ... (this) 期望 Qt 父子链清理,但 timer 不会因 parent 而 stop(事件循环里仍可能正在派发 timeout)。
修复方案:析构开头先 stop 所有 timer 并 disconnect。
7.3 ⚠️【高】QStackedWidget 切页面共享 PicScene 同步
切页面后 testprintwidget 修改了 pPicScene,mainwidget 缓存的 item 引用会失效。
修复方案:用一个全局 SceneManager 单点维护 PicScene 与 items;或在切页面时显式重新绑定。
7.4 ⚠️【高】saveFPGA*** 槽函数 unsigned char* data 协议解析
- 未校验
len;偏移data[5+i]直接访问; - 协议帧若被截断,会读到栈/堆外。
修复方案:所有偏移加if (len < kHeader + N) return;校验。
7.5【中】lambda 捕获 raw pointer
e.g. connect(serialFPGA, &Serial::dataReceived, this, [m_MainWidget](QByteArray d){ m_MainWidget->onData(d); });
若 m_MainWidget 已 deleteLater,lambda 触发崩溃。
修复方案:捕获 QPointer<MainWidget> p = m_MainWidget;,使用前判空。
7.6【中】showScheduleShiftsEditor / openDatetimeEditor 接收 item* 异步使用
修复方案:参数改 QPointer<PicTextItem>。
7.7【中】restartSerialPort / closeSerial 并发竞争
两路串口都可能在主线程和子线程同时被关闭/重启,无锁。
修复方案:增加 QMutex 或调度到串口所在线程后再操作(QMetaObject::invokeMethod(serial, ..., Qt::QueuedConnection))。
7.8【中】子 widget 是否重复 new
代码里有 if(!m_xxx) m_xxx = new ... 不一致,部分入口直接 new,重复 new 会泄漏旧的。
修复方案:统一懒加载工厂。
7.9【低】部分 deleteLater 后立刻设置成员为 nullptr 可避免后续再访问悬空。
八、修复优先级与建议步骤
按修复成本与收益排序,建议按以下顺序处理:
-
P0 立即修(避免 crash)
- 3.1 / 3.2 / 3.3 / 3.4 / 3.5 / 3.7 :scene 目录 Item 类的空指针、索引越界、UB 返回值;改动小、稳定性收益最大。
- 5.1 / 5.2 / 5.3 / 5.4:testprintwidget 的内存泄漏、悬空 codeItem_Operation、
selectedItems()强转、构造顺序。 - 7.1 / 7.2:InkJetPrinter 析构里的线程与 timer。
-
P1 短期修(避免数据错误/偶发崩溃)
- 3.8 / 3.9 / 3.11;4.1 / 4.2 / 4.5;5.5 / 5.6;6.1 / 6.2 / 6.3;7.3 / 7.4 / 7.5。
-
P2 后续整改(架构层)
- 引入
QPointer<>/shared_ptr替换裸指针存储 item; - 把对话框对 item 的引用改为「id + 查表」模式,避免任何悬空;
- 串口/线程操作集中到独立 service 类,加锁;
- 统一 PicScene 所有权(建议 InkJetPrinter 持有,子 widget 只 bind)。
- 引入
-
P3 代码风格层面
- 用
qgraphicsitem_cast替换 C 风格强转; - 用
QFile::exists+QSaveFile增强 IO; - 把
goto重写为函数式; - 编译开
-Wall -Wextra -Wreturn-type -Wuninitialized把潜在 UB 编译时挡住。
- 用
九、回归验证建议
修完后建议至少跑通以下场景,能稳定不崩即视为通过:
- 空场景:打开测试打印 → 不放任何 item → 直接预览/打印 → 关闭。
- 复制粘贴:连续复制粘贴 50 次 + 删除 + 撤销。
- 极端文本:item 文本设为「空」「单字符」「100 字符」「中英混排」「Emoji」「不存在的字体」。
- 图片项:选不存在的图片路径 / 损坏图 / 巨型图(>4096px)。
- 条码 / 二维码:编辑器打开期间,外部点「全部删除」/ 加载模板。
- ScheduleShifts:打开班次编辑后删除 item 再返回保存。
- 串口 / FPGA:拔掉 USB → 触发
restartSerialPort→ 重新插入。 - 进入退出:连续 30 次
InkJetPrintershow/hide / 退出程序,无内存增长且无 crash。 - 跨页切换:mainwidget ↔ testprintwidget ↔ systemmanage 反复切换 100 次。
- 打印:连续打印 1000 次(含日期变量、计数器、班次),观察
imageToPrintData是否越界。
十、文档说明
- 本文件路径:
doc/Scene_Modules_Bug_Inspection_Report.md - 排查未涉及代码的修改,所有「修复方案」仅作为后续提交的参考。
- 部分 mainwidget 相关 6.1–6.7 项标注为「待复核」,原因是受当前会话上下文限制未能逐行通读 mainwidget.cpp 全文。建议在确认上述 P0/P1 修复方向后,再单独安排对
mainwidget.cpp/h的全文复核(建议输出 6.x 项的精确行号与代码片段)。
下一步:请检查本文档,确认修复方向与优先级;确认后我再按 P0 → P1 顺序提交代码改动。
文档审阅
十一、本次会话修复结论(2026-05-10 追加)
11.1 已修复项
- 3.2 pictextitem.cpp
mouseReleaseEvent/keyPressEvent未判空scene():已在两个事件函数入口加if(!scene())提前返回,避免 item 离场期间触发scene()->update()/scene()->selectedItems()解引用空指针。
11.2 复核结论(无需修复)
- 3.11 piccodeitem 中
m_dateVarTimer风险:复核scene/piccodeitem.h后确认当前类中并不存在m_dateVarTimer成员;该项原为基于代码模式的预防性提示,目前不构成实际隐患,标记为「不适用」。
11.3 用户已自行修复(来自上文「澄清」栏汇总)
- 3.1
clampItemPos未判空scene()—— 已修复 - 3.3
strToImage0 宽/0 高 QImage —— 已修复 - 3.5
m_currCounterValues越界 —— 已在updateVariants入口校验 - 3.7
setBoldMultiple缺少返回值 —— 已修复 - 3.8 PicImageItem 加载失败仍使用旧对象 —— 已修复
- 3.9 PicScheduleShiftItem 返回临时对象引用 —— 已修复
11.4 用户决定不修复(按澄清栏)
- 3.4
itemChange()clamp 逻辑未生效(含ItemSceneChange笔误)—— 用户表示该段代码使用已久未发现异常,暂不修复 - 3.6
setSource忽略入参 ——source/setSource机制准备弃用,不予修复 - 3.10 文档对象 stylesheet —— 全面自绘,不予修复
- 3.12
clipImage使用 goto +originRect未使用 —— 不予修复
11.5 仍待处理项(按优先级)
- P0:5.1 / 5.2 / 5.3 / 5.4(testprintwidget 内存泄漏、悬空
codeItem_Operation、C 风格强转、构造顺序);7.1 / 7.2(InkJetPrinter 析构线程与 timer 清理)。 - P1:4.1 / 4.2 / 4.5(编辑器持有 item 裸指针);5.5 / 5.6;6.1 / 6.2 / 6.3(mainwidget 待全文复核);7.3 / 7.4 / 7.5。
- P2/P3:架构层
QPointer/id+查表替换裸指针存储、串口/线程加锁、qgraphicsitem_cast替换 C 风格强转等。
下一步建议:可单独安排对
mainwidget.cpp/h的全文复核,输出 6.1–6.7 项的精确行号与代码片段后再决定修复。其余 P0 项(testprintwidget / InkJetPrinter)可按本节排序逐项推进。