PyQT 崩溃(底层 C/C++ 对象已被删除)“在”清空 QTreeWidget 后

0 投票
2 回答
947 浏览
提问于 2025-04-17 12:46

我正在尝试为一个QTreeWidget构建实时搜索功能,也就是说我有一个QLineEdit,当我输入时,它会过滤QTreeWidget中显示的结果。

目前,我是通过QTreeWidget.findItems()来获取“仍然显示的项目”。

foundItems  = mainForm.ui.treeShips.findItems(text,QtCore.Qt.MatchContains)

然后,我用

mainForm.ui.treeShips.clear()

来清空QTreeWidget(mainForm.ui.treeShips)。

接着,我想用

mainForm.ui.treeShips.addTopLevelItems(foundItems)

将“仍然显示的项目”添加回去,但程序却崩溃了,提示“底层的C/C++对象已被删除”。

我最初的想法是,清空treeShips时,foundItems的内容也被清空了,因为foundItems中的对象(print(foundItems))和treeShips中的对象有相同的地址,当程序想要使用这个列表时就崩溃了。

有没有人知道怎么解决这个问题,或者有没有更好的方法来实现这样的“搜索过滤”?

(希望我能正确描述我的问题 :))

谢谢,祝好!

2 个回答

0

每当你在一个 QTreeWidgetItem 上调用 clear 函数时,里面的项目都会被删除,所以你遇到的错误并不奇怪。你可以在下面的 QTreeWidget 实现的摘录中看到这一点:

void QTreeWidget::clear()
{
    Q_D(QTreeWidget);
    selectionModel()->clear();
    //the treeModel here is QTreeModel, refer to snippet below
    d->treeModel()->clear();
}


void QTreeModel::clear()
{
    SkipSorting skipSorting(this);
    for (int i = 0; i < rootItem->childCount(); ++i) {
        QTreeWidgetItem *item = rootItem->children.at(i);
        item->par = 0;
        item->view = 0;
        delete item;
    }
....
}

关于你提到的搜索功能,这里有一个不错的示例,展示了如何实现搜索功能(不是实时的)。点击这里查看。虽然是C++代码,但希望你能理解。

如果你想要实现实时搜索,你需要将 QLineEditvoid textChanged(const QString & text) 信号连接到一个处理搜索的槽函数。

希望这能解答你的问题。

1

我找到了一个解决办法,灵感来自Neox的第二个想法。

我遍历树中的所有项目,把隐藏标志设置为真(setHidden(True)),然后再遍历找到的项目,把隐藏标志设置为假(我觉得这样可以,因为这两个列表的地址是一样的)。

for item in mainForm.ui.treeShips.findItems("",QtCore.Qt.MatchContains):
    item.setHidden(True)

for item in foundItems:
    item.setHidden(False)

不过我不知道这样做是不是有点不太干净,但确实有效 :)

希望这能帮助到其他遇到同样问题的人。

撰写回答