Ответ 1
В классе родительского виджета вы можете использовать следующее:
QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
delete widget;
}
Я использую конструктор QWidget(QWidget *parent)
. Этот родительский виджет содержит много дочерних виджетов. Мне нужно очистить все дочерние виджеты от родителя во время выполнения. Как я могу это сделать?
В классе родительского виджета вы можете использовать следующее:
QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
delete widget;
}
Предыдущий ответ неверен! Вы не можете использовать findChildren
для удаления дочерних элементов виджетов, потому что Qt4 findChildren
рекурсивно отображает список. Таким образом, вы удалите дочерние элементы детей, которые затем могут быть удалены дважды, что может привести к сбою вашего приложения.
В более общем плане, в Qt, перечисление указателей QObject
и их удаление один за другим опасно, так как уничтожение объекта может привести к разрушению других объектов из-за механизма родительского права или путем подключения destroyed()
в слот deleteLater()
. Следовательно, уничтожение первых объектов в списке может привести к недействительности следующих.
Вам нужно перечислить детские виджеты:
Чтобы решить проблему рекурсивности, отмеченную @galinette, вы можете просто удалить виджеты в цикле while
while ( QWidget* w = findChild<QWidget*>() )
delete w;
Из Qt docs
Следующий фрагмент кода показывает безопасный способ удаления всех элементов из макета:
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child;
}
Подведение итогов и дополнение:
Для Qt5 в одной строке:
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
Для Qt5 для большого количества детей, используя setUpdatesEnabled():
parentWidget->setUpdatesEnabled(false);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
parentWidget->setUpdatesEnabled(true);
Обратите внимание, что это не исключение! В то время как Qt в это время не появляется, чтобы генерировать исключения здесь, сигнал destroy() может быть связан с кодом, который выполняет бросок, или может быть брошен переопределенный Object:: childEvent (QChildEvent *).
Лучше было бы использовать вспомогательный класс:
class UpdatesEnabledHelper
{
QWidget* m_parentWidget;
public:
UpdatesEnabledHelper(QWidget* parentWidget) : m_parentWidget(parentWidget) { parentWidget->setUpdatesEnabled(false); }
~UpdatesEnabledHelper() { m_parentWidget->setUpdatesEnabled(true); }
};
...
UpdatesEnabledHelper helper(parentWidget);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
Для Qt4:
QList<QWidget*> childWidgets = parentWidget->findChildren<QWidget*>();
foreach(QWidget* widget, childWidgets)
if (widget->parentWidget() == parentWidget)
delete widget;
Удаление из QLayout работает как в Qt4, так и в Qt5:
QLayoutItem* child;
while (NULL != (child = layout->takeAt(0))) // or nullptr instead of NULL
delete child;
QObjects (и, следовательно, QWidgets) удаляют себя (автоматически) из своего родителя в их (QObject) деструкторе.