pyqt - PyQt4 setParent vs deleteLater -


i have layout add lot of custom widgets layout.addwidget(widget). later want remove custom widgets , add new ones. i'm confused on best way when comes deletelater , setparent(none). example, here's cleanup function that's called widgets in layout:

def _removefilterwidgetfromlayout(self, widget):     """remove filter widget"""      self._collection_layout.removewidget(widget)     widget.setparent(none)     widget.deletelater() 

i have suspicion not of these lines needed cleanup memory used widget. i'm unsure of happening c++ , python references widget.

here's understand c++ , python references qobjects in pyqt.

i believe when add widget layout widget becomes child of layout. so, if call removewidget parent relationship broken have clean c++ , python reference myself since widget has no other parent. call setparent explicit way of removing parent relationship layout. call deletelater meant take care of c++ reference.

the python reference garbage collected because widget variable goes out of scope, , there no other python objects pointing widget.

do need call setparent , deletelater or deletelater enough clean up?

as side note, i've found calling setparent(none) expensive function call in scenario. can speed entire cleanup process removing call. i'm not sure if deletelater enough clean correctly. here's profiling output line_profiler:

line #      hits         time  per hit   % time  line contents ==============================================================   2167                                               @profile   2168                                               def _removefilterwidgetfromlayout(self, widget):   2169                                                   """remove filter widget"""   2170   2171       233         1528      6.6      1.0          self._collection_layout.removewidget(widget)   2172       233       143998    618.0     97.9          widget.setparent(none)   2173       233         1307      5.6      0.9          widget.deletelater() 

when using pyqt4 there 'accepted' way cleanup? should use setparent, deletelater, or both?

probably easiest way see what's going on step through things in interactive session:

>>> parent = qtgui.qwidget() >>> child = qtgui.qwidget() >>> layout = qtgui.qhboxlayout(parent) >>> layout.addwidget(child) >>> child.parent() layout false >>> child.parent() parent true 

so layout not become parent of widget. makes sense, because widgets can have other widgets parents, , layouts not widgets. widgets added layout have parents reset parent of layout (whenever gets one).

>>> item = layout.itemat(0) >>> item <pyqt4.qtgui.qwidgetitem object @ 0x7fa1715fe318> >>> item.widget() child true 

since there no parent/child relationship bewteen layouts , widgets contain, different api needed access underlying objects. items owned layout, ownership of underlying objects remains unchanged.

>>> layout.removewidget(child) >>> child.parent() parent true >>> layout.count() 0 >>> repr(layout.itemat(0)) 'none' >>> item <pyqt4.qtgui.qwidgetitem object @ 0x7fa1715fe318> 

at point, layout has deleted item (because had ownership of it), , no longer holds references contained widget. given this, no longer safe python wrapper item (the interpreter crash if tried call of methods).

>>> child.deletelater() >>> parent.children() [<pyqt4.qtgui.qhboxlayout object @ 0x7fa1715fe1f8>] >>> child.parent() traceback (most recent call last):   file "<stdin>", line 1, in <module> runtimeerror: wrapped c/c++ object of type qwidget has been deleted >>> 

since still have ownership of child widget, can call deletelater on it. , can seen traceback, delete underlying c++ object, python wrapper object left behind. however, wrapper (eventually) deleted garbage collector, once remaining python references gone. note there never need call setparent(none) during process.

one final point: above interpreter session misleading, because event-queue processed every time line executed. means effects of deletelater seen immediately, not case if code run script. immediate deletion in script, need use sip module:

>>> import sip >>> sip.delete(child) 

Comments

Popular posts from this blog

Email notification in google apps script -

c++ - Difference between pre and post decrement in recursive function argument -

javascript - IE11 incompatibility with jQuery's 'readonly'? -