Several webpages say that QTreeWidgetItem
can be deleted by deleting or QTreeWidget.clear
ing. But my code sample below doesn't seem to do so. Am I doing anything wrong?
#!/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()
Printed as:
TreeWidgetItemChild init
Before clearing
After clearing
TreeWidgetItemChild del
Looks to me TreeWidgetItemChild
gets deleted upon the termination of process, not by any of my deletion actions.
By calling
del i
you are just deleting the reference not the actual C++ Object(referent) it refers to, not the object itself.Change your
TreeWidgetItemChild.__del__
function to:You're confusing tree items (i.e., tree nodes) with the widgets that a given item can contain.
The following example creates a
QTreeWidget
and adds two items to it: a top level item and a nested one. Removing the comments you can see how both of them are removed from the tree.For removing both types of items from the tree you need the items index. If you have a reference to the item you want to remove you can get the corresponding index with the
indexOfTopLevelItem
andindexOfChild
functions.Python is different from C++ in the sense of memory management/deleting objects. Python has a garbage collector (GC) that manages destroying of the objects automatically. That occurs when the reference count of an object reaches zero.
del i
only means 'decrement the reference count by one'. It never results in a direct call to__del__
.__del__
of an object is only called when reference count reaches to zero and is about to be garbage collected. (Although this is true for CPython, it's not guaranteed for every implementation. It depends on the GC implementation. So you should not rely on__del__
at all)Keeping story short, the call time of
__del__
is ambiguous. You should never call__del__
(or any other__foo__
special methods) directly. In fact, for the reasons above you should rather avoid the use of__del__
at all (usually).Apart from that, there is another issue.
This does not remove an item from
QTreeWidget
. As the name suggests, it removes a widget from an item, not theQTreeWidgetItem
. It's counterpart to thesetItemWidget
method, not theaddTopLevelItem
method.If you need to remove a specific item from the tree, you should use
takeTopLevelItem
.tree.clear()
is fine. It will remove every top level item from the tree.As an epilogue to Avaris' excellent answer, let's flog an even more general-purpose approach applicable to all widgets and widget items (rather than merely top-level tree widget items). Is this supposed Shangri-La too good to be true?
To quoth the Mario: "Waaaa! Let's-a-go!"
Here We-A-Go
Specifically, if your project leverages:
PySide2, import the
shiboken2
module and pass each tree widget item to be deleted to theshiboken2.delete()
function ala:PyQt5, import the
sip
module and pass each tree widget item to be deleted to thesip.delete()
function ala:Nothing Could Possibly Go Wrong
Yes, this behaves as expected under all platforms and (PyQt5|PySide2) releases. The Python-specific
sip.delete()
andshiboken2.delete()
methods are high-level wrappers around the underlying C++delete
operator – and operate exactly identically. In the case ofQTreeWidgetItem
instances, this reproduces the C++ behaviour of immediately removing the passed item from its parent tree.Yes, it is both glorious and sketchy. Thanks to alexisdm's relevant answer elsewhere for the motivational impetus behind this overwrought answer. Glory be to alexisdm.