12

いくつかの Web ページは、 delete またはingQTreeWidgetItemによって削除できると述べています。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私の削除アクションではなく、プロセスの終了時に削除されるように見えます。

4

4 に答える 4

15

Python は、メモリ管理/オブジェクトの削除という意味で C++ とは異なります。Python には、オブジェクトの破棄を自動的に管理するガベージ コレクター (GC) があります。これは、オブジェクトの参照カウントがゼロになったときに発生します。

del i「参照カウントを 1 減らす」ことのみを意味します。を直接呼び出すことはありません__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()結構です。ツリーからすべての最上位アイテムを削除します。

于 2012-10-25T08:58:49.707 に答える
4

呼び出すことで、オブジェクト自体ではdel iなく、実際の C++ オブジェクト ( referent ) ではなく、参照を削除するだけです。

TreeWidgetItemChild.__del__関数を次のように変更します。

def __del__(self):
    treeWidget = self.treeWidget()
    #removing the QTreeItemWidget object
    treeWidget.takeTopLevelItem(treeWidget.indexOfTopLevelItem(self))
    print 'TreeWidgetItemChild del'
于 2012-10-25T08:25:34.897 に答える
3

ツリーアイテム(つまり、ツリーノード)を、特定のアイテムに含めることができるウィジェットと混同しています。

次の例では、を作成し、QTreeWidgetそれに2つのアイテムを追加します。トップレベルのアイテムとネストされたアイテムです。コメントを削除すると、両方がツリーからどのように削除されるかを確認できます。

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

ツリーから両方のタイプのアイテムを削除するには、アイテムインデックスが必要です。削除するアイテムへの参照がある場合は、indexOfTopLevelItemおよびindexOfChild関数を使用して対応するインデックスを取得できます。

于 2012-10-25T10:15:44.573 に答える