[PyQt] Mis-transfer in QLayout.addWidget

Martin Teichmann martin.teichmann at gmail.com
Tue Jul 8 08:58:00 BST 2014


Hi Phil, Hi List,

QLayout and most of its sub-classes have a method addWidget
that add a widget to the layout. Within the sip specification,
the widget parameter is declared /Transfer/, meaning that the
ownership of the widget is transferred to the layout. Unfortunately,
Qt transfers the ownership to the parent widget of the layout,
not the layout itself. This is unfortunate, because once the layout
is deleted, the widget might be garbage collected as well, while
the parent widget still holds a reference to it. This leads to the
weird situation of a python-created widget to loose all its python
attributes.

I added a script that illustrates the problem. It raises and
AttributeError in the very last line, which should not be there.

Greetings

Martin Teichmann

-------- test script follows ------
from PyQt4.QtGui import QLayout, QApplication, QWidget, QHBoxLayout
from PyQt4.QtCore import pyqtSignal, pyqtSlot
from functools import partial

import gc
import sys

app = QApplication([])

class Widget(QWidget):
    sig = pyqtSignal()

    @pyqtSlot()
    def slot(self):
        print 'SLOT', self.bla


    def slat(self, x):
        print 'SLAT', self.bla

parent = QWidget()
w = Widget(parent)
w.bla = 'b'

ws = Widget(parent)
ws.sig.connect(w.slot)

Widget(w).sig.connect(partial(w.slat, 3)) # keep w alive

layout = QHBoxLayout()
parent.setLayout(layout)
# the parent is a referrer
assert w.parent() in gc.get_referrers(w)
layout.addWidget(w)
# the parent still should be referrer, but is not
# assert w.parent() in gc.get_referrers(w) # assert will fail

# a workaround looks as follows:
#w.setParent(parent)

layout.setParent(None)

del layout
del w

# the following lines illustrate the problem
# the first signal emission works well,
# the second raises an AttributeError
ws.sig.emit()
gc.collect()
ws.sig.emit()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20140708/04ef1a30/attachment.html>


More information about the PyQt mailing list