问题
I am working on Qt application. There I am creating layout and adding sublayout. I have seen that calling addLayout() sets as parent the container layout. Does that implies than when I delete superlayout its descendants will get deleted too?
QWidget* centralWidget = new QWidget(this);
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
QFormLayout *formLayout = new QFormLayout;
mainLayout->addLayout(formLayout);
Will deleting centralWidget delete formLayout? Thanks and regards
回答1:
Concerning Lifetime Management (or in other words: which deletes what), there is an extra chapter in Qt doc.:
Object Trees & Ownership
QObjects organize themselves in object trees. When you create a QObject with another object as parent, it's added to the parent's children() list, and is deleted when the parent is. It turns out that this approach fits the needs of GUI objects very well. For example, a QShortcut (keyboard shortcut) is a child of the relevant window, so when the user closes that window, the shortcut is deleted too.
...
QWidget, the fundamental class of the Qt Widgets module, extends the parent-child relationship. A child normally also becomes a child widget, i.e. it is displayed in its parent's coordinate system and is graphically clipped by its parent's boundaries. For example, when the application deletes a message box after it has been closed, the message box's buttons and label are also deleted, just as we'd want, because the buttons and label are children of the message box.
You can also delete child objects yourself, and they will remove themselves from their parents. For example, when the user removes a toolbar it may lead to the application deleting one of its QToolBar objects, in which case the tool bar's QMainWindow parent would detect the change and reconfigure its screen space accordingly.
The debugging functions QObject::dumpObjectTree() and QObject::dumpObjectInfo() are often useful when an application looks or acts strangely.
Looking for doc. of QVBoxLayout::addLayout()
, I came to:
void QBoxLayout::addLayout(QLayout *layout, int stretch = 0)
Adds layout to the end of the box, with serial stretch factor stretch.
See also insertLayout(), addItem(), and addWidget().
which is not very helpful but following the link I ended up in
void QLayout::addItem(QLayoutItem *item)
Implemented in subclasses to add an item. How it is added is specific to each subclass.
This function is not usually called in application code. To add a widget to a layout, use the addWidget() function; to add a child layout, use the addLayout() function provided by the relevant QLayout subclass.
Note: The ownership of item is transferred to the layout, and it's the layout's responsibility to delete it.
The ownership of item is transferred to the layout, and it's the layout's responsibility to delete it.
To illustrate this, I made a small sample testQLayoutDelete.cc
similar to the exposed code of OP:
#include <QtWidgets>
#define DEBUG_DELETE(CLASS) \
struct CLASS: Q##CLASS { \
CLASS(QWidget *pQParent = nullptr): Q##CLASS(pQParent) { } \
virtual ~CLASS() { qDebug() << #CLASS"::~"#CLASS"();"; } \
}
DEBUG_DELETE(Widget);
DEBUG_DELETE(VBoxLayout);
DEBUG_DELETE(FormLayout);
DEBUG_DELETE(PushButton);
int main(int argc, char *argv[])
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup UI
QWidget *pQCentralWidget = new Widget();
QVBoxLayout *pQMainLayout = new VBoxLayout(pQCentralWidget);
QFormLayout *pQFormLayout = new FormLayout;
QPushButton *pQButton = new PushButton();
pQFormLayout->addRow(QString("The button: "), pQButton);
pQMainLayout->addLayout(pQFormLayout);
pQCentralWidget->show();
// enter runtime loop
int ret = app.exec();
// clean up explicitly (for illustration of recursive destruction)
qDebug() << "delete pQCentralWidget;";
delete pQCentralWidget;
// done
qDebug() << "return ret;";
return ret;
}
I made a little help macro DEBUG_DELETE()
to derive every involved Qt widget/layout class, where the overloaded destructor makes a respective debug output.
A Qt project file testQLayoutDelete.pro
to compile it:
SOURCES = testQLayoutDelete.cc
QT += widgets
Compiled and tested in cygwin64 on Windows 10:
$ qmake-qt5 testQLayoutDelete.pro
$ make && ./testQLayoutDelete
Qt Version: 5.9.4
After clicking the × button, the interesting output appears:
delete pQCentralWidget;
Widget::~Widget();
VBoxLayout::~VBoxLayout();
FormLayout::~FormLayout();
PushButton::~PushButton();
return ret;
$
来源:https://stackoverflow.com/questions/53140601/does-deleting-layout-deletes-its-sublayouts