如何删除QTreeWidgetItem

Isa*_*acS 9 python qt qtreewidget qtreewidgetitem pyside

有几个网页说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()
Run Code Online (Sandbox Code Playgroud)

印刷为:

TreeWidgetItemChild init
Before clearing
After clearing
TreeWidgetItemChild del
Run Code Online (Sandbox Code Playgroud)

对我来说TreeWidgetItemChild,在流程终止时会删除,而不是通过我的任何删除操作.

Ava*_*ris 10

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

del i仅表示'将参考计数减1'.它永远不会导致直接调用__del__.__del__只有当引用计数达到零并且即将被垃圾收集时才调用对象.(虽然CPython也是如此,但并不能保证每个实现都有.这取决于GC的实现.所以你根本不应该依赖它__del__)

保持故事简短,通话时间__del__不明确.你不应该直接打电话__del__(或任何其他__foo__特殊方法).事实上,由于上​​述原因,你应该完全避免使用__del__(通常).

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

tree.removeItemWidget(i, 0)
Run Code Online (Sandbox Code Playgroud)

这不会删除项目QTreeWidget.顾名思义,它从项目中删除了一个小部件,而不是QTreeWidgetItem.它与setItemWidget方法相对应,而不是addTopLevelItem方法.

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

tree.takeTopLevelItem(tree.indexOfTopLevelItem(i))
Run Code Online (Sandbox Code Playgroud)

tree.clear()很好.它将从树中删除每个顶级项目.


Cec*_*rry 5

作为Avaris优秀答案的尾声,让我们提出一种适用于所有小部件和小部件项(而不仅仅是顶级树小部件项)的更通用的方法。这所谓的香格里拉是不是好得令人难以置信?

\n\n

用马里奥的话来说:“Waaaa!Let\'sa-go!”

\n\n

我们出发吧

\n\n

具体来说,如果您的项目利用:

\n\n
    \n
  • PySide2,导入shiboken2模块并将每个要删除的树小部件项传递给函数shiboken2.delete()ala:

    \n\n
    # Well, isn\'t that nice. Thanks, Qt Company.\nfrom PySide2 import shiboken2\n\n# Add this item to this tree.\ntree = QTreeWidget()\nitem = TreeWidgetItemChild()\ntree.addTopLevelItem(item)\n\n# Remove this item from this tree. We\'re done here, folks.\nshiboken2.delete(item)\n
    Run Code Online (Sandbox Code Playgroud)
  • \n
  • PyQt5,导入sip模块并将每个要删除的树小部件项传递给函数sip.delete()ala:

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

不可能出错

\n\n

是的,这在所有平台和 (PyQt5|PySide2) 版本下的行为都符合预期。Python 特有的sip.delete()shiboken2.delete()方法是底层 C++ 运算符 \xe2\x80\x93 的高级包装器delete,并且操作完全相同。在实例的情况下QTreeWidgetItem,这会重现立即从其父树中删除传递的项的 C++ 行为。

\n\n

是的,它既辉煌又粗略。感谢alexisdm在其他地方的相关答案,为这个过度紧张的答案背后提供了动力。荣耀归于亚历克西斯

\n