执行函数两次时 Pyside 崩溃

Pyside crashes when executing function twice

为什么当我 运行 函数 setup_controls() 两次时我的应用程序崩溃。

我是否遗漏了一个 'parent/self' 在设计中很关键的地方?

import sys
from PySide import QtGui, QtCore

class QCategoryButton(QtGui.QPushButton):
    def __init__(self, Text, treeitem, parent=None):
        super(QCategoryButton, self).__init__(Text, parent)
        self.treeitem = treeitem

    def mousePressEvent(self, event):
        mouse_button = event.button()
        if mouse_button == QtCore.Qt.LeftButton:
            self.treeitem.setExpanded(not self.treeitem.isExpanded())

class Example(QtGui.QWidget):

    def __init__(self,):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):

        # formatting
        self.resize(300, 300)
        self.setWindowTitle("Example")

        # widgets
        self.ui_treeWidget = QtGui.QTreeWidget()
        self.ui_treeWidget.setRootIsDecorated(False)
        self.ui_treeWidget.setHeaderHidden(True)
        self.ui_treeWidget.setIndentation(0)

        self.setup_controls()
        # self.setup_controls()

        # layout
        self.mainLayout = QtGui.QGridLayout(self)
        self.mainLayout.addWidget(self.ui_treeWidget)
        self.show()    

    def setup_controls(self):
        # Add Category
        pCategory = QtGui.QTreeWidgetItem()
        self.ui_treeWidget.addTopLevelItem(pCategory)
        self.ui_toggler = QCategoryButton('Settings', pCategory)
        self.ui_treeWidget.setItemWidget(pCategory, 0, self.ui_toggler)

        pFrame = QtGui.QFrame(self.ui_treeWidget)
        pLayout = QtGui.QVBoxLayout(pFrame)
        self.ui_ctrl = QtGui.QPushButton('Great')
        self.ui_ctrlb = QtGui.QPushButton('Cool')
        pLayout.addWidget(self.ui_ctrl)
        pLayout.addWidget(self.ui_ctrlb)

        pContainer = QtGui.QTreeWidgetItem()
        pContainer.setDisabled(False)
        pCategory.addChild(pContainer)
        self.ui_treeWidget.setItemWidget(pContainer, 0, pFrame)

# Main
# ------------------------------------------------------------------------------
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

setItemWidget 方法获取传递给它的小部件的所有权。如果您不保留它的引用,它可以通过 Python 获得 garbage-collected。但是 Qt 当然对 Python 一无所知,所以当它随后尝试访问不再存在的小部件时...... boom!

这是有问题的行:

    self.ui_toggler = QCategoryButton('Settings', pCategory)

在第二次调用时,存储在 self.ui_toggler 中的先前小部件将被删除,因为没有其他引用(在 Python 端)。所以你应该这样做:

    ui_toggler = QCategoryButton('Settings', pCategory, self)
    self.ui_treeWidget.setItemWidget(pCategory, 0, ui_toggler)