如何删除QTreeWidgetItem(How to delete QTreeWidgetItem)

2019-08-01 21:22发布

一些网页说QTreeWidgetItem可以通过删除或删除QTreeWidget.clear荷兰国际集团。 但我的代码示例如下似乎并没有这样做。 难道我做错了什么?

#!/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()

打印为:

TreeWidgetItemChild init
Before clearing
After clearing
TreeWidgetItemChild del

在我看来TreeWidgetItemChild获取过程中,没有任何的缺失我在行动终止删除。

Answer 1:

Python是在存储器管理/删除对象的意义上由C ++不同。 Python有一个垃圾收集器(GC)管理自动销毁的对象。 当一个对象的引用计数达到零发生。

del i只意味着“减一参考计数”。 它永远不会导致直接调用__del____del__对象的当引用计数达到零,并即将被垃圾收集仅调用。 (虽然这是CPython的真实的,它不能保证每个执行。这取决于GC的实现。所以,你不应该依赖于__del__在所有)

保持总而言之,的通话时间__del__是模糊的。 你永远不应该调用__del__ (或任何其他__foo__直接特殊的方法)。 事实上,你上面的原因,而应避免使用__del__所有(通常情况下)。

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

tree.removeItemWidget(i, 0)

这并不删除项目QTreeWidget 。 正如其名,它会从一个项目,而不是一个小部件 QTreeWidgetItem 。 这是对应于setItemWidget方法,而不是addTopLevelItem方法。

如果您需要从树中删除一个特定的项目,你应该使用takeTopLevelItem

tree.takeTopLevelItem(tree.indexOfTopLevelItem(i))

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



Answer 2:

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

更改TreeWidgetItemChild.__del__功能:

def __del__(self):
    treeWidget = self.treeWidget()
    #removing the QTreeItemWidget object
    treeWidget.takeTopLevelItem(treeWidget.indexOfTopLevelItem(self))
    print 'TreeWidgetItemChild del'


Answer 3:

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

下面的示例创建一个QTreeWidget ,并增加了两个项目吧:一个顶级项目和嵌套的一个。 删除你可以看到他们两个从树中删除的意见。

#!/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功能。



Answer 4:

作为尾声阿瓦里斯 “ 出色答卷 ,让我们鞭打适用于所有控件和控件项目(而不是仅仅顶级树控件项目)一个更加通用的做法。 这是所谓的香格里拉太好了,是真的吗?

为了答曰马里奥: “Waaaa Let's-A-去!”

在这里,我们-A-围棋

特别是,如果你的项目利用:

  • PySide2,导入shiboken2模块,并通过每个树插件项目被删除到shiboken2.delete()函数的ala:

     # Well, isn't that nice. Thanks, Qt Company. from PySide2 import shiboken2 # Add this item to this tree. tree = QTreeWidget() item = TreeWidgetItemChild() tree.addTopLevelItem(item) # Remove this item from this tree. We're done here, folks. shiboken2.delete(item) 
  • PyQt5,导入sip模块,并通过每个树插件项目被删除到sip.delete()函数的ala:

     # Well, isn't that not-quite-so-nice. You are now required to import any # arbitrary PyQt5 submodule *BEFORE* importing "sip". Hidden side effects are # shameful, of course, but we don't make the rules. We only enforce them. For # detailed discussion, see: # # http://pyqt.sourceforge.net/Docs/PyQt5/incompatibilities.html#pyqt-v5-11 # # If your project requires PyQt5 >= 5.11, the following compatibility hack may # be safely reduced to the following one-liner: # # from PyQt5 import sip from PyQt5 import QtCore import sip # Add this item to this tree. tree = QTreeWidget() item = TreeWidgetItemChild() tree.addTopLevelItem(item) # Remove this item from this tree. sip.delete(item) 

没有什么可能出问题

是的,这表现在所有的平台和预期(PyQt5 | PySide2)版本。 具体Python的sip.delete()shiboken2.delete()方法是底层的C左右的高级别包装++ delete操作员-和准确的操作相同。 在的情况下QTreeWidgetItem情况下,这立即再现从其父树移除通过项目的C ++行为。

是的,这是既光荣而粗略。 由于alexisdm的其他地方相关答案为此寝食难安答案背后的动机动力。 荣耀归于alexisdm 。



文章来源: How to delete QTreeWidgetItem