Удаляет ли макет удаление его подслоев?

Я работаю над приложением Qt. Там я создаю макет и добавляю подслой. Я видел, что вызов addLayout() устанавливает в качестве родителя макет контейнера. Означает ли это, что когда я удаляю суперслой, удаляются и его потомки?

QWidget* centralWidget = new QWidget(this);
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
QFormLayout *formLayout = new QFormLayout;
mainLayout->addLayout(formLayout);

Будет ли удаление centralWidget удалять formLayout? Спасибо и всего наилучшего

1 ответ

Решение

Что касается Lifetime Management (или другими словами: что и что удаляет), в Qt doc есть дополнительная глава:

Деревья объектов и собственность

QObjects организуются в деревья объектов. Когда вы создаете QObject с другим объектом в качестве родителя, он добавляется в список дочерних элементов родителя () и удаляется, когда родительский объект есть. Оказывается, этот подход очень хорошо соответствует потребностям объектов GUI. Например, QShortcut (сочетание клавиш) является дочерним элементом соответствующего окна, поэтому, когда пользователь закрывает это окно, сочетание также удаляется.

...

QWidget, фундаментальный класс модуля Qt Widgets, расширяет отношения родитель-потомок. Ребенок обычно также становится дочерним виджетом, то есть он отображается в системе координат своего родителя и графически обрезается по границам его родителя. Например, когда приложение удаляет окно сообщения после того, как оно было закрыто, кнопки и метка окна сообщения также удаляются, как мы и хотели, потому что кнопки и метка являются дочерними элементами окна сообщения.

Вы также можете удалить дочерние объекты самостоятельно, и они удалят себя от своих родителей. Например, когда пользователь удаляет панель инструментов, это может привести к тому, что приложение удалит один из его объектов QToolBar, и в этом случае родительский элемент QMainWindow панели инструментов обнаружит изменение и соответствующим образом перенастроит свое экранное пространство.

Функции отладки QObject::dumpObjectTree() и QObject::dumpObjectInfo() часто полезны, когда приложение выглядит или действует странно.

Ищу док. из QVBoxLayout::addLayout(), Я пришел к:

void QBoxLayout:: addLayout (макет QLayout *, int stretch = 0)

Добавляет макет в конец поля с последовательным коэффициентом растяжения.

Смотрите также insertLayout(), addItem() и addWidget().

что не очень полезно, но по ссылке, в которой я оказался

void QLayout::addItem(QLayoutItem *item)

Реализовано в подклассах для добавления элемента. Как это добавляется, зависит от каждого подкласса.

Эта функция обычно не вызывается в коде приложения. Чтобы добавить виджет в макет, используйте функцию 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

Окно testQLayoutDelete

После нажатия кнопки × появляется интересный вывод:

delete pQCentralWidget;
Widget::~Widget();
VBoxLayout::~VBoxLayout();
FormLayout::~FormLayout();
PushButton::~PushButton();
return ret;

$
Другие вопросы по тегам