The correct way to clean widgets in pyqt

What is the “correct” or idiomatic way to clean / remove widgets when using PyQt4?

Consider the following code:

choices = ['a', 'b', 'c'] checkboxes = [] layout = QtGui.QVBoxLayout() dialog = MyDialog() for c in choices: checkboxes.append(QtGui.QCheckBox(c) layout.addWidget(chkbox) dialog.setLayout(layout) for c in checkboxes: c.setParent(None) c.deleteLater() c = None 

The code above uses setParent() , deleteLater() and setting the object to None . Is all this necessary?

Another possible scenario: I have a dialog with a bunch of widgets on it and you want to remove these widgets and add new ones. I don’t want to “leak” old widgets, but I’m not sure what is the right way to do something like this.

It seems to me that deleteLater() will never be needed. Does it just decrease the link count? If so, would you not only set the variable None, but would you do the same?

+6
source share
1 answer

The first thing you should remember is to use the parent / child relationship for your widgets. When you do this, they will be owned by Qt and will automatically clear all children when the parent is removed.

 dialog = MyDialog() for c in choices: checkboxes.append(QtGui.QCheckBox(c, parent=dialog)) layout.addWidget(chkbox) 

In this situation, all the checkboxes will be correctly cleared when the dialog is deleted. This handles one part of your question. I understand that you implicitly have a parent set when you add them to the layout. But you should not clear this parent before deleting. it a parental relationship that automatically removes the child. Not a reference account. The reference aspect would be the thing on the python side where it would collect garbage when there are no more references to it.

deleteLater very important to use when you want a delete to occur when the control returns to eventloop. This is also a safe way to remove widgets when you remove some of the layout and add new ones:

 # clear a layout and delete all widgets # aLayout is some QLayout for instance while aLayout.count(): item = aLayout.takeAt(0) item.widget().deleteLater() 

These widgets will actually be deleted after this method completes. deleteLater also useful for deleting a widget under which a slot or event is currently located. For example, QPushButton, which can delete itself when clicked.

Also no need to set c = None . As soon as the parent is deleted and starts deleting all its children, recursively, your python references to this object will be invalid. Therefore, all you have to do is simply not use them anymore. If they are on the list, clear the list. Access to them will increase the value of RuntimeError: wrapped C/C++ object of %S has been deleted , which they will be deleted.

+15
source

All Articles