Sign in to follow this  
TheComet

PyQt4 - takeAt() returning a QWidgetItem?

Recommended Posts

TheComet    3900
Hi,
 
I've discovered some very strange behaviour when trying to delete a QWidget from a QGridLayout. The following code demonstrates this behaviour:
 
>>> from PyQt4 import QtGui
>>> import sys
>>> app = QtGui.QApplication(sys.argv)
>>> grid_layout = QtGui.QGridLayout()
>>> grid_layout.addWidget(QtGui.QWidget())
>>> item = grid_layout.takeAt(0)
>>> item.deleteLater()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'QWidgetItem' object has no attribute 'deleteLater'
 
I swear this has worked before.
 
This makes no sense to me whatsoever. Firstly, why is it returning a QWidgetItem when I inserted a QWidget to begin with? Secondly, every Qt object derives from QObject, and deleteLater() is a method of QObject, so that method should exist. What's going on here?
 
Additional info:
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Edited by TheComet

Share this post


Link to post
Share on other sites
Aardvajk    13207

Can't speak for Python, but in the C++ Qt, takeAt has always returned a QWidgetItem. When you add a widget to a layout, it creates a QWidgetItem under the scenes, which is what is always (and has always) been returned by things like itemAt(), takeAt() etc.

 

Layouts store QLayoutItems, not widgets, so a widget has to be contained in a descendant of QLayoutItem.

 

You can access the QWidgetItem::widget() if you need to. If memory serves, there is some odd behaviour with ownership here and you need to delete the widget, then the widget item to properly remove it, although again this is C++ and I'm not 100% sure I'm remembering that right.

Share this post


Link to post
Share on other sites
TheComet    3900

It's strange because I could have sworn I've used the following code before in other projects:

while layout.count():
    layout.takeAt(0).deleteLater()

Anyway, the following seems to work just fine:

layout.takeAt(0).widget().deleteLater()
Edited by TheComet

Share this post


Link to post
Share on other sites
Aardvajk    13207

It's strange because I could have sworn I've used the following code before in other projects:

while layout.count():
    layout.takeAt(0).deleteLater()
Anyway, the following seems to work just fine:
layout.takeAt(0).widget().deleteLater()

I'm not sure the QLayoutItem is being deleted there. No idea if it matters in Python but in C++ takeAt transfers ownership of the QLayoutItem to the caller and the layout no longer owns it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this