1

Why does my application crash when i run the function setup_controls() twice.

Am I missing a 'parent/self' somewhere that is critical in the design?

enter image description here

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_())
JokerMartini
  • 5,674
  • 9
  • 83
  • 193

1 Answers1

1

The setItemWidget method takes ownership of the widget that is passed to it. If you don't keep a reference it, it could get garbage-collected by Python. But of course Qt knows nothing about Python, so when it subsequently tries to access the widget that is no longer there ... boom!

This is the problematic line:

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

On the second call, the previous widget stored in self.ui_toggler will get deleted, because there is no other reference held for it (on the Python side). So instead you should do this:

    ui_toggler = QCategoryButton('Settings', pCategory, self)
    self.ui_treeWidget.setItemWidget(pCategory, 0, ui_toggler)
ekhumoro
  • 115,249
  • 20
  • 229
  • 336