如何清除父窗口小部件中的所有窗口小部件?

时间:2010-10-15 07:52:19

标签: qt qwidget

我正在使用构造函数QWidget(QWidget *parent)。此父窗口小部件包含许多子窗口小部件。我需要在运行时从父级清除所有子窗口小部件。我怎么能这样做?

5 个答案:

答案 0 :(得分:22)

以前的答案是错误的!!您无法使用findChildren删除小部件的子级,因为Qt4的findChildren 递归会列出子级。因此,您将删除子项的子项,然后可能会删除两次,这可能会导致您的应用程序崩溃。

更一般地说,在Qt中,获取QObject指针列表并逐个删除它们是危险的,因为由于父级所有权机制,或者通过连接对象,销毁对象可能会链破其他对象destroyed()deleteLater()广告位发出信号。因此,销毁列表中的第一个对象可能会使下一个对象无效。

您需要通过以下方式列出子窗口小部件:

  • 如果您使用的是Qt5,那么将Qt :: FindDirectChildrenOnly标志传递给findChild(当问题被提出时它不存在...)
  • 使用QLayout函数列出项目
  • 使用QObject :: children,并且对于每个测试,如果它是使用isWidgetType()或者演员
  • 的小部件
  • 在循环中使用findChild()并删除结果,直到它返回空指针

答案 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;
}