我正在使用构造函数QWidget(QWidget *parent)
。这个父窗口包含许多子窗口。我需要在运行时清除所有子窗口。我应该怎么做?
之前的答案是错误的!!你不能使用 findChildren
来删除一个 widget 的子控件,因为 Qt4 的 findChildren
是递归地 列出所有子控件。因此,你会删除子控件的子控件,这可能会导致应用程序崩溃。
更一般地说,在 Qt 中,将 QObject
指针列表逐个删除是危险的,因为销毁一个对象可能会级联销毁其他对象,这是由于父对象拥有机制或将 destroyed()
信号连接到 deleteLater()
插槽所致。因此,删除列表中的第一个对象可能会使下一个对象失效。
你需要按照以下方式列出子控件:
findChildren
上使用Qt::FindDirectChildrenOnly
以避免双重删除。 - Drew McGowenfindChildren
可以使用Qt::FindDirectChildrenOnly
进行调用。这非常具有误导性。 - Kuba hasn't forgotten MonicaqDeleteAll
使用 delete
删除容器中的项目。手动循环并调用 deleteLater
是否更合适/更安全? - GPhilowhile ( QWidget* w = findChild<QWidget*>() )
delete w;
总结和补充:
对于Qt5,简单概括:
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
对于许多孩子来说,使用setUpdatesEnabled()的Qt5:
parentWidget->setUpdatesEnabled(false);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
parentWidget->setUpdatesEnabled(true);
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;
QObject(因此也包括QWidgets)在其(QObject)析构函数中自动从其父对象中删除自己。
findChildren<QWidget*>("", Qt::FindDirectChildrenOnly)
找不到任何东西,但是 findChildren<QWidget*>(QString(), Qt::FindDirectChildrenOnly)
可行。 - Sasha来自Qt 文档
下面的代码片段展示了一种安全的方式去除布局中的所有项:
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child;
}
QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
delete widget;
}