首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何删除QTreeWidgetItem

如何删除QTreeWidgetItem
EN

Stack Overflow用户
提问于 2012-10-25 13:47:08
回答 3查看 14.3K关注 0票数 12

有几个网页说,删除可以通过QTreeWidget.clearQTreeWidgetItem来删除。但是我下面的代码样本似乎不能做到这一点。我做错什么了吗?

代码语言:javascript
复制
#!/usr/bin/python
import sys
from PySide.QtGui import QApplication, QWidget, QTreeWidget, QTreeWidgetItem
#from PyQt4.QtGui import QApplication, QWidget, QTreeWidget, QTreeWidgetItem # Result was the same with `PySide`
import time

class TreeWidgetItemChild(QTreeWidgetItem):
    def __init__(self):
        super(TreeWidgetItemChild, self).__init__()
        print 'TreeWidgetItemChild init'

    def __del__(self):
        print 'TreeWidgetItemChild del'

def test_QTree_clear_children():
    tree = QTreeWidget()
    tree.setHeaderLabel('funksoul')
    i = TreeWidgetItemChild()    
    tree.addTopLevelItem(i)    
    print 'Before clearing'
    #tree.clear()                  # Didn't call destructor (__del__)
    #tree.removeItemWidget (i, 0)  # Didn't call destructor
    #i.__del__()                   # Called destructor but it's called again afterward
    del i                          # Didn't call destructor
    time.sleep(1)
    print 'After clearing'

if __name__ == '__main__':
    app = QApplication(sys.argv)
    test_QTree_clear_children()

打印为:

代码语言:javascript
复制
TreeWidgetItemChild init
Before clearing
After clearing
TreeWidgetItemChild del

在我看来,TreeWidgetItemChild在进程终止时被删除,而不是通过我的任何删除操作。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-10-25 16:58:50

Python与C++在内存管理/删除对象方面有所不同。Python有一个垃圾收集器(GC),它自动管理对象的销毁。当对象的引用计数达到零时会发生这种情况。

del i只表示“将引用计数减一”。它不会导致对__del__的直接调用。仅当引用计数达到零且即将被垃圾回收时,才会调用对象的__del__。(虽然这对于CPython是正确的,但并不保证每个实现都是这样的。这取决于GC实现。所以你根本不应该依赖于__del__ )

简单来说,__del__的调用时间是模棱两可的。您永远不应该直接调用__del__ (或任何其他__foo__特殊方法)。事实上,由于上述原因,您应该完全避免使用__del__ (通常如此)。

除此之外,还有另一个问题。

代码语言:javascript
复制
tree.removeItemWidget(i, 0)

这不会从QTreeWidget中删除项目。顾名思义,它从项目中删除小部件,而不是QTreeWidgetItem。它对应于setItemWidget方法,而不是addTopLevelItem方法。

如果需要从树中删除特定项目,则应使用takeTopLevelItem

代码语言:javascript
复制
tree.takeTopLevelItem(tree.indexOfTopLevelItem(i))

tree.clear()很好。它将从树中删除所有顶级项目。

票数 14
EN

Stack Overflow用户

发布于 2012-10-25 16:25:35

通过调用del i,您只是删除了引用,而不是它引用的实际C++对象(Referent),而不是对象本身。

TreeWidgetItemChild.__del__函数更改为:

代码语言:javascript
复制
def __del__(self):
    treeWidget = self.treeWidget()
    #removing the QTreeItemWidget object
    treeWidget.takeTopLevelItem(treeWidget.indexOfTopLevelItem(self))
    print 'TreeWidgetItemChild del'
票数 4
EN

Stack Overflow用户

发布于 2012-10-25 18:15:45

您将树项目(即树节点)与给定项目可以包含的小部件相混淆。

下面的示例创建一个QTreeWidget并向其中添加两个项:顶级项和嵌套项。删除注释,您可以看到它们都是如何从树中删除的。

代码语言:javascript
复制
#!/usr/bin/env python
import sys
from PyQt4.QtGui import *

class MyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.tree = QTreeWidget(self)
        self.setCentralWidget(self.tree)
        self.tree.setHeaderLabel('funksoul')
        i = QTreeWidgetItem(self.tree, ['top level'])   
        self.tree.addTopLevelItem(i)
        j = QTreeWidgetItem(i ,['nested level'])
        #i.takeChild(0)
        #self.tree.takeTopLevelItem(0)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    ui = MyMainWindow()
    ui.show()
    sys.exit(app.exec_())

要从树中删除这两种类型的项目,您需要项目索引。如果您有对要删除的项的引用,则可以使用indexOfTopLevelItemindexOfChild函数获取相应的索引。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13062327

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档