How to delete QTreeWidgetItem

匿名 (未验证) 提交于 2019-12-03 08:46:08

问题:

Several webpages say that QTreeWidgetItem can be deleted by deleting or QTreeWidget.clearing. 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.

回答1:

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.

tree.removeItemWidget(i, 0) 

This does not remove an item from QTreeWidget. As the name suggests, it removes a widget from an item, not the QTreeWidgetItem. It's counterpart to the setItemWidget method, not the addTopLevelItem method.

If you need to remove a specific item from the tree, you should use takeTopLevelItem.

tree.takeTopLevelItem(tree.indexOfTopLevelItem(i)) 

tree.clear() is fine. It will remove every top level item from the tree.



回答2:

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:

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


回答3:

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.

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

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 and indexOfChild functions.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!