Об удалении, удалении виджетов и макетов в Qt 4

(я использую Qt 4.7, Windows 7, 64 бит).

Я создал пользовательскую таблицу. Каждая строка представляет собой горизонтальную компоновку с виджетами. Строки хранятся в QList для легкого доступа, а также для детей. Строки также добавляются внутри родительского виджета.

Если я изменяю размер родительского виджета, я вычисляю новые размеры, удаляю все и снова создаю его.

Моя проблема в том, что я не хочу удалять виджет. Только когда я очищаю таблицу, я делаю это.

Так как у меня есть виджеты внутри QList и внутри родительских макетов, как я могу удалить все виджеты в каждой строке, удалить все макеты, а затем добавить их в новые макеты?

Если я делаю: takeAt (0) для каждого элемента внутри каждого макета, у меня есть QLayoutItem с виджетами внутри... Как я могу удалить layoutItem без удаления виджета?.... Как удалить виджет без убить его, независимо от того, находится ли он у родителя или ребенка? Поскольку существует множество методов для удаления: removeItem, removeWidget... в макете, но не takeWidget... просто takeAt(), и он дает Qlayoutitem.

Я пробовал несколько способов, но я все еще вижу виджеты независимо от того, что с ними произошло.

Вопросы об этом:

  • Когда виджет удаляется? Если я беру Widget (индекс) из макета, он удаляется некоторое время сам по себе? это произойдет, если у меня есть указатель на него в другом списке?

  • removeAt (index) выполняет метод удаления виджета?

Ответ 1

Ok. Я заработал. Позвольте мне объяснить, как это происходит, сохраняя виджетов.

Виджет известен его макетом. И вы удалите его по макету. Выполняя:

layout()->removeAt(widget);
delete widget;

Если вы используете takeAt (index) в QLayout (или его дочерних), он дает вам QLayoutItem. Чтобы получить доступ к виджету внутри, просто используйте widget(). Но нет способа удалить виджет, не удаляя его. Таким образом, этот подход недействителен.

В Документах указывается способ удаления элементов:

QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0)  {
    ...
    delete child;
}

Особо следует отметить в Qt следующее: Если у вас есть дерево иерархического дерева гирархии, добавленное с помощью addLayout() внутри макетов, независимо от того, насколько глубоко ваш виджет вставлен, вы можете удалить его из дочерних макетов или любого из родительских, если путь дерева из макета и этот элемент построены из дочерних макетов.

Самое простое - сохранить список указателей ко всем элементам в пользовательской таблице. При очистке таблицы для ее восстановления просто сделайте это внутри своего виджета:

  CustomTableItem* item;
  while ( !items_.isEmpty() && ( (item = items_.takeFirst()) != 0 ) ){
    layout()->removeWidget(item);
    delete item; // It works no matter where the item is
  }

  items_.clear(); // clear the list afterwards.

И он отлично работает, сам обновляет макет. Если вы хотите сохранить элементы, просто пропустите "delete item;" и использовать их впоследствии.

Важно отметить, что разные функции "удалить" работают по-разному (как я понимаю в Qt Docs) в QList или подобных виджетах и ​​в QLayout. В QList removeAt фактически удаляет объект.

(Qt 4.7 QList Docs) "Удаляет элемент в позиции индекса i. я должно быть допустимой позицией индекса в списке (т.е. 0 <= я < size())."

В QLayout, removeWidget или removeItem не удаляют элемент/виджет, у вас есть возможность удалить его, как и раньше.

(Qt 4.7 QLayout Docs) "Удаляет виджет виджетов из макета. После этого вызова это ответственность вызывающего абонента, чтобы дать виджете разумную геометрию или верните виджет в макет."

Надеюсь, это поможет. Если вы видите какую-либо ошибку, вы можете сказать мне, и я отредактирую ответ!

Подробнее об удалении здесь: fooobar.com/questions/123574/...

Ответ 2

Виджет в Qt является регулярным объектом С++ и может быть удален с помощью оператора С++ delete как любой другой объект:

delete myWidget;

В Qt всегда существует отношение родитель-потомок между виджетами. Когда родительский виджет будет уничтожен, он удалит все его дочерние элементы. Обычно вам не нужно думать о явном удалении каких-либо виджетов, кроме виджетов верхнего уровня, то есть окон и диалогов. Qt позаботится об удалении любых дочерних виджетов.

QList::removeAt(int) не удаляет объект, который удаляется, он удаляет только объект из списка. Если вы также хотите удалить объект, вам нужно будет сделать что-то вроде:

delete myList.takeAt(0);

Это относится ко всем функциям, таким как removeAt(int), takeAt(int), takeFirst() и т.д. Они никогда не удаляют объекты, они удаляют их только из контейнера (список, макет, прокрутка и т.д.). В большинстве случаев владение виджетами затем передается вызывающему абоненту (вызывающий отвечает за удаление виджета при разрыве отношения родитель-ребенок), но не предполагайте, что это всегда так, всегда читайте документацию о функции.