Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyQt: RuntimeError: wrapped C/C++ object has been deleted

If I run this code:

    #!/usr/local/bin/    python3

import sys 
from PyQt4.QtCore import *
from PyQt4.QtGui import *


class Window(QMainWindow):

    def __init__(self):
        super().__init__()
        self.button1 = QPushButton("1")
        self.button2 = QPushButton("2")
        self.setCentralWidget(self.button1)
        self.button1.clicked.connect(lambda: self.setCentralWidget(self.button2))
        self.button2.clicked.connect(lambda: self.setCentralWidget(self.button1))
        self.show()

if __name__ == '__main__':

    import sys 
    app = QApplication(sys.argv)
    window = Window()
    sys.exit(app.exec_())

...I get this output:

Traceback (most recent call last):
  File "test.py", line 16, in <lambda>
    self.button2.clicked.connect(lambda: self.setCentralWidget(self.button1))
RuntimeError: wrapped C/C++ object of type QPushButton has been deleted

I do not understand why the object is being deleted. Window should maintain a reference to it. I have thoroughly investigated these posts: Understanding the “underlying C/C++ object has been deleted” error Can a PyQt4 QObject be queried to determine if the underlying C++ instance has been destroyed?

Why is the button being deleted?

like image 947
Brian Avatar asked Jul 29 '13 01:07

Brian


4 Answers

This answer to this question is as found here: Python PySide (Internal c++ Object Already Deleted)

Apparently, assigning one widget to QMainWindow using setCentralWidget and then assigning another widget with setCentralWidget will cause the underlying c++ QWidget to be deleted, even though I have an object that maintains reference to it.

Note: QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time.

like image 134
Brian Avatar answered Nov 13 '22 00:11

Brian


Brain's answer explains the problem perfectly. This Link explain things in more detail.

My solution to this problem was to set the widgets as attributes of the object (e.g. simply using self.label = ... instead of label = ... in your class methods). You might want to do the same for any layouts attached to the widget.

This way you create a copy of the widget so that when C++ memory cleanup occurs, you still have a reference to the widget.

Hope this helps.

like image 28
Ankit Bindal Avatar answered Nov 13 '22 00:11

Ankit Bindal


This problem also occurs in PyQT5 when you run a continuous thread and close the mainwindow/dialog without closing thread first but in background the thread is processing. When you again open the window the second thread generated and delete the pre-existed widgets. You need to exit the thread first before re-run it. You can exit the thread by put the check on visibility of any widget in the mainwindow/dialog

            **if self.widget.isVisible() == False:
                break**
like image 2
Hsnyn Asif Avatar answered Nov 13 '22 00:11

Hsnyn Asif


In another case, the solution was to add all child objects to a detached layout first, and adding the layout to the parent layout as the last step. That is:

    l = QGridLayout()
    l.addWidget(QLabel("child1"), 0, 0)
    l.addWidget(QLabel("child2"), 0, 1)
    ...
    parentLayout.addLayout(l)
like image 1
user3076105 Avatar answered Nov 12 '22 23:11

user3076105