<div dir="ltr"><div>Hi Phil, Hi List,<br><br></div><div>QLayout and most of its sub-classes have a method addWidget<br>that add a widget to the layout. Within the sip specification,<br></div><div>the widget parameter is declared /Transfer/, meaning that the <br>
ownership of the widget is transferred to the layout. Unfortunately,<br></div><div>Qt transfers the ownership to the parent widget of the layout,<br></div><div>not the layout itself. This is unfortunate, because once the layout<br>
is deleted, the widget might be garbage collected as well, while<br>the parent widget still holds a reference to it. This leads to the<br>weird situation of a python-created widget to loose all its python<br>attributes.<br>
<br></div><div>I added a script that illustrates the problem. It raises and <br>AttributeError in the very last line, which should not be there.<br><br></div><div>Greetings<br><br>Martin Teichmann<br><br></div><div>-------- test script follows ------<br>
from PyQt4.QtGui import QLayout, QApplication, QWidget, QHBoxLayout<br>from PyQt4.QtCore import pyqtSignal, pyqtSlot<br>from functools import partial<br><br>import gc<br>import sys<br><br>app = QApplication([])<br><br>class Widget(QWidget):<br>
    sig = pyqtSignal()<br><br>    @pyqtSlot()<br>    def slot(self):<br>        print 'SLOT', self.bla<br><br><br>    def slat(self, x):<br>        print 'SLAT', self.bla<br><br>parent = QWidget()<br>w = Widget(parent)<br>
w.bla = 'b'<br><br>ws = Widget(parent)<br>ws.sig.connect(w.slot)<br><br>Widget(w).sig.connect(partial(w.slat, 3)) # keep w alive<br><br>layout = QHBoxLayout()<br>parent.setLayout(layout)<br># the parent is a referrer<br>
assert w.parent() in gc.get_referrers(w)<br>layout.addWidget(w)<br># the parent still should be referrer, but is not<br># assert w.parent() in gc.get_referrers(w) # assert will fail<br><br># a workaround looks as follows:<br>
#w.setParent(parent)<br><br>layout.setParent(None)<br><br>del layout<br>del w<br><br># the following lines illustrate the problem<br># the first signal emission works well,<br># the second raises an AttributeError<br>ws.sig.emit()<br>
gc.collect()<br>ws.sig.emit()<br><br><br></div></div>