QTableWidget交换行后Cell Widget消失问题求助
QTableWidget交换行后Cell Widget消失的问题分析与修复
核心错误点
QList::insert参数误用
代码最后一行的m_protectionWidgets->insert(upperIndex, 1, protectionWidget);完全错误:Qt的QList::insert没有三参数重载用于插入单个元素,这里传入的1会被解析为要插入的元素数量,导致插入1个无效指针(int强制转指针),同时原protectionWidget被removeAt(index)移除后,列表元素混乱,最终导致表格无法正确关联Widget,引发Widget消失。冗余指针复制(无功能影响但易混淆)
ProtectionWidget *protectionWidgetCopy = protectionWidget;只是复制指针,没有实际作用,直接使用原指针即可。
修复后的代码
connect(upButton, &QPushButton::clicked, this, [this, protectionWidget]() { int index = m_protectionWidgets->indexOf(protectionWidget); int upperIndex = index - 1; if (upperIndex >= 0) { // 交换第一列的文本项 QTableWidgetItem *nameItem = m_protectionsTable->takeItem(index, 0); QTableWidgetItem *upperNameItem = m_protectionsTable->takeItem(upperIndex, 0); m_protectionsTable->setItem(upperIndex, 0, nameItem); m_protectionsTable->setItem(index, 0, upperNameItem); // 交换第1列的ProtectionWidget QWidget *currentWidget = m_protectionsTable->cellWidget(index, 1); QWidget *upperWidget = m_protectionsTable->cellWidget(upperIndex, 1); m_protectionsTable->setCellWidget(upperIndex, 1, currentWidget); m_protectionsTable->setCellWidget(index, 1, upperWidget); // 交换第2列的按钮组 QWidget *currentButtons = m_protectionsTable->cellWidget(index, 2); QWidget *upperButtons = m_protectionsTable->cellWidget(upperIndex, 2); m_protectionsTable->setCellWidget(upperIndex, 2, currentButtons); m_protectionsTable->setCellWidget(index, 2, upperButtons); // 直接交换列表中的元素,避免remove/insert的参数错误 m_protectionWidgets->swap(index, upperIndex); } });
关键说明
- Qt中一个Widget只能有一个父对象,调用
setCellWidget时,框架会自动将Widget的父对象从原单元格切换到新单元格,无需手动处理父对象移除。 - 使用
QList::swap交换元素比removeAt+insert更高效,且完全避免了参数误用的风险。
内容的提问来源于stack exchange,提问作者willy_j
相关产品推荐
相关产品推荐

