我正在使用构造函数QWidget(QWidget *parent)
。此父窗口小部件包含许多子窗口小部件。我需要在运行时从父级清除所有子窗口小部件。我怎么能这样做?
答案 0 :(得分:22)
以前的答案是错误的!!您无法使用findChildren
删除小部件的子级,因为Qt4的findChildren
递归会列出子级。因此,您将删除子项的子项,然后可能会删除两次,这可能会导致您的应用程序崩溃。
更一般地说,在Qt中,获取QObject
指针列表并逐个删除它们是危险的,因为由于父级所有权机制,或者通过连接对象,销毁对象可能会链破其他对象destroyed()
向deleteLater()
广告位发出信号。因此,销毁列表中的第一个对象可能会使下一个对象无效。
您需要通过以下方式列出子窗口小部件:
答案 1 :(得分:14)
要处理@galinette指出的递归问题,你可以在while循环中删除小部件
while ( QWidget* w = findChild<QWidget*>() )
delete w;
答案 2 :(得分:5)
来自Qt docs
以下代码片段显示了从布局中删除所有项目的安全方法:
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child;
}
答案 3 :(得分:5)
总结和补充:
对于一行中的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)析构函数中从其父级中自动(自动)删除它们。
答案 4 :(得分:-7)
您可以在父窗口小部件类中使用以下内容:
QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
delete widget;
}