Относительно управления временем жизни (или другими словами: что и что удаляет), есть дополнительная глава в Qt doc .:
QObjects организуются в деревья объектов. Когда вы создаете QObject с другим объектом в качестве родителя, он добавляется в список children () родителя и удаляется, когда родительский объект есть. Оказывается, этот подход очень хорошо соответствует потребностям объектов GUI. Например, QShortcut (сочетание клавиш) является дочерним элементом соответствующего окна, поэтому, когда пользователь закрывает это окно, сочетание также удаляется.
...
QWidget, фундаментальный класс модуля Qt Widgets, расширяет отношения родитель-потомок. Дочерний объект обычно также становится дочерним виджетом, то есть он отображается в системе координат своего родителя и графически обрезается по границам его родителя. Например, когда приложение удаляет окно сообщения после того, как оно было закрыто, кнопки и метка окна сообщения также удаляются, как нам хотелось бы, потому что кнопки и метка являются дочерними элементами окна сообщения.
Вы также можете удалять дочерние объекты самостоятельно, и они удаляют себя от своих родителей. Например, когда пользователь удаляет панель инструментов, это может привести к тому, что приложение удалит один из его объектов QToolBar, и в этом случае родительский элемент QMainWindow панели инструментов обнаружит изменение и соответствующим образом перенастроит свое экранное пространство.
Функции отладки QObject :: dumpObjectTree () и QObject :: dumpObjectInfo () часто полезны, когда приложение выглядит или действует странно.
Ищу док. из QVBoxLayout::addLayout()
, я пришел к:
Добавляет макет в конец поля, с последовательным коэффициентом растяжения.
См. Также insertLayout (), addItem () и addWidget ().
, что не очень полезно, но по ссылке я попал в
Реализовано в подклассах для добавления элемента. Как это добавляется, зависит от каждого подкласса.
Эта функция обычно не вызывается в коде приложения. Чтобы добавить виджет в макет, используйте функцию addWidget (); чтобы добавить дочерний макет, используйте функцию addLayout (), предоставленную соответствующим подклассом QLayout.
Примечание: Право собственности на элемент передается макету, и макет несет ответственность за его удаление.
Право собственности на элемент передается макету, и макет несет ответственность за его удаление.
Чтобы проиллюстрировать это, я сделал небольшой образец testQLayoutDelete.cc
, похожий на открытый код 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;
}
Я сделал небольшой справочный макрос DEBUG_DELETE()
, чтобы получить каждый задействованный класс виджетов / классов Qt, где перегруженный деструктор делает соответствующий вывод отладки.
Файл проекта Qt testQLayoutDelete.pro
для его компиляции:
SOURCES = testQLayoutDelete.cc
QT += widgets
Скомпилировано и протестировано в cygwin64 в Windows 10:
$ qmake-qt5 testQLayoutDelete.pro
$ make && ./testQLayoutDelete
Qt Version: 5.9.4
После нажатия кнопки & times; появляется интересный вывод:
delete pQCentralWidget;
Widget::~Widget();
VBoxLayout::~VBoxLayout();
FormLayout::~FormLayout();
PushButton::~PushButton();
return ret;
$