Удаляет ли макет удаление его подслоев? - PullRequest
0 голосов
/ 04 ноября 2018

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

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

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

1 Ответ

0 голосов
/ 06 ноября 2018

Относительно управления временем жизни (или другими словами: что и что удаляет), есть дополнительная глава в Qt doc .:

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

QObjects организуются в деревья объектов. Когда вы создаете QObject с другим объектом в качестве родителя, он добавляется в список children () родителя и удаляется, когда родительский объект есть. Оказывается, этот подход очень хорошо соответствует потребностям объектов 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

Window of testQLayoutDelete

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

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

$
...