3

I can't seem to find much guidance on this issue anywhere online. I have been learning PySide and have noticed that half of the examples out there just set the parent of QStuff to None while other examples will set it to an object. I realize there may be a garbage collection issue at play. Say I have a QWidget object and I create and reference a QThing with its parent set to QWidget, then I .add the QThing to QWidget. It seems like I should then have circular references somewhere. Python does reference counting, so this would mean that the objects won't get garbage collected. Even something like

self.addWidget(QLabel('label', self))

would result in a circular reference (Though I imagine this case is handled by PySide.) Maybe I am worrying too much and all this is handled, I don't know.

In Short: What is the right way to use parents in PySide?

Cory-G
  • 1,025
  • 14
  • 26
  • 2
    (C)Python uses reference counting **plus** garbage collection, for exactly that reason. So circular-referencers are a non-issue most of the time (especially in python3.4+). – Bakuriu Sep 16 '14 at 19:58

1 Answers1

5

Two things at work here:

Qt

Qt organizes its object in object trees via the parent relationship. When you dispose an object all children are destroyed too (on the C side). Also properties like style are inherited via this relationship. It turns out that this is very useful for GUI objects, after all when you close a dialog you probably also want to get rid of the buttons in the dialog.

See also Object Trees & Ownership

Python (CPython)

Python deletes objects when they fall out of scope automatically. For example buttons that you thought you had disappear because Python garbage collected them already. Turns out that setting the parent correctly everywhere helps. For example with layouts the easiest way is to specify the parent directly in the construction of the layout (saves a call to setLayout).

But if you still have a python reference to a button for example, but the widget was destroyed by Qt you may get a "RuntimeError: Internal C++ object already deleted.".

So a sufficient extent of setting parents helps a lot to write bugfree code with Qt and Python.

In your example:

self.addWidget(QLabel('label', self))

the parent is set twice after another. First when the inner part QLabel('label', self) is created and second when addWidget is called (see documentation of QLayout). Instead of doing the same thing twice, why not only doing it once?

self.addWidget(QLabel('label'))

And for circular references per se, see Should I worry about circular references in Python?

Community
  • 1
  • 1
NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
  • Thanks. That was a great answer. So I guess I should prefer letting `addWidget` do it's thing and only add the parent if things really need it. This will avoid some weird errors too. I noticed that if I set the parents of each tab of a `QTabWidget`, but don't call `addTab`, it will draw the tabs over the top of the widget all at once. Things get really funky when you call `addTab` on only one tab. It then draws the added tab overlapped with the not added tabs (this may just be a bug... I think I am using 1.1.0) So sticking to `addWidget` and `addTab` seems a bit safer. – Cory-G Sep 16 '14 at 20:42
  • 1
    @CoryB Yes definitely. Setting parents is mostly done automatically when you call addXXX. Just let it do its work. And always use layouts. That way never widgets are drawn on top of each other. – NoDataDumpNoContribution Sep 17 '14 at 07:24