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