I'm having issues with a non-Qt object falling out of scope and being garbage collected by Python. In the generic example below, I create an object when one button is clicked and want to use that object when the other button is clicked. After the slot for the 1st button is finished executing, the object is garbage collected.
# Started from http://zetcode.com/gui/pysidetutorial/firstprograms/ and
# connections program from chap 4 of Summerfield's PyQt book
import sys
from PySide import QtGui
def createThingy():
thing1 = thingy("thingName", 3, wid)
lbl1.setText(thing1.name + " created.")
return
def updateNum():
lbl1.setText("number: " + str(thing1.number))
return
class thingy(object):
def __init__(self, name, number, mainWindow):
self.name = name
self.number = number
def func1(self):
return "Something to return"
def rtnNum(self):
return "Num: " + str(self.number)
app = QtGui.QApplication(sys.argv)
wid = QtGui.QWidget()
wid.resize(250, 150)
wid.setWindowTitle('Example')
btn1 = QtGui.QPushButton("Create thingy")
btn2 = QtGui.QPushButton("Number")
lbl1 = QtGui.QLabel("---")
vlayout = QtGui.QVBoxLayout()
vlayout.addWidget(btn1)
vlayout.addWidget(btn2)
vlayout.addWidget(lbl1)
wid.setLayout(vlayout)
btn1.clicked.connect(createThingy)
btn2.clicked.connect(updateNum)
wid.show()
wid.raise_()
sys.exit(app.exec_())
This sort of behavior is mentioned on the PySide pitfalls page, https://wiki.qt.io/PySide_Pitfalls, as well as the question "Python PySide (Internal c++ Object Already Deleted)" https://stackoverflow.com/a/5339238/2599816 (this question doesn't really answer my question since the author's solution is to avoid the problem).
Because the object is not a Qt object, passing it a parent is not a viable option. Additionally, I do not want to create the object at the start of the program as some other questions/answers have suggested elsewhere (can't find links to them again). Further, the object should not be modified to solve this problem but the solution should be implemented in the GUI, i.e. keep the object generic for use as a library in other programs.
Thanks for the help.
It is being garbage collected because the scope is lost once the function execution ends. You need to save the reference, and there are two ways of doing it:
QWidget
implementation, saving the created object in the widget object (via self).Please let me know if I wasn't clear or accurate enough.
Hope it helps.
Cheers.
Create a subclass of QWidget
to keep all the child objects as attributes:
import sys
from PySide import QtGui
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.resize(250, 150)
self.setWindowTitle('Example')
self.btn1 = QtGui.QPushButton("Create thingy")
self.btn2 = QtGui.QPushButton("Number")
self.lbl1 = QtGui.QLabel("---")
vlayout = QtGui.QVBoxLayout()
vlayout.addWidget(self.btn1)
vlayout.addWidget(self.btn2)
vlayout.addWidget(self.lbl1)
self.setLayout(vlayout)
self.btn1.clicked.connect(self.createThingy)
self.btn2.clicked.connect(self.updateNum)
def createThingy(self):
self.thing1 = thingy("thingName", 3, wid)
self.lbl1.setText(self.thing1.name + " created.")
def updateNum(self):
self.lbl1.setText("number: " + str(self.thing1.number))
class thingy(object):
def __init__(self, name, number, mainWindow):
self.name = name
self.number = number
def func1(self):
return "Something to return"
def rtnNum(self):
return "Num: " + str(self.number)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
wid = Widget()
wid.show()
sys.exit(app.exec_())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With