如何清除父Widget中的所有Widget?

发布于 2024-09-28 02:27:19 字数 97 浏览 3 评论 0原文

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

I am using the constructor QWidget(QWidget *parent). This parent widget contains a lot of child widgets. I need to clear all the child widgets from the parent at runtime. How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

皇甫轩 2024-10-05 02:27:19

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

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

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

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

Previous answer is wrong!! You cannot use findChildren to delete a widget's children, because Qt4's findChildren recursively lists children. Therefore, you will delete children of children, which then may be deleted twice, potentially crashing your app.

More generally, in Qt, taking a list of QObject pointers and deleting them one by one is dangerous, as destroying an object may chain-destroy other objects, due to the parent ownership mechanism, or by connecting a destroyed() signal to a deleteLater() slot. Therefore, destroying the first objects in the list may invalidate the next ones.

You need to list children widgets either by:

  • Passing the Qt::FindDirectChildrenOnly flag to findChild if you are using Qt5 (which did not exist when the question was asked...)
  • Using QLayout functions for listing items,
  • Using QObject::children, and for each test if it is a widget using isWidgetType() or a cast
  • Using findChild() in a loop and delete the result until it returns a null pointer
心房敞 2024-10-05 02:27:19

要解决 @galinette 指出的递归问题,您只需在 while 循环中删除小部件即可

while ( QWidget* w = findChild<QWidget*>() )
    delete w;

To take care of the recursivity problem pointed out by @galinette you can just remove the widgets in a while loop

while ( QWidget* w = findChild<QWidget*>() )
    delete w;
嘿哥们儿 2024-10-05 02:27:19

总结补充:

对于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;

QObject(以及 QWidget)在其 (QObject) 析构函数中从其父级中(自动)删除自身。

Summarizing and supplementing:

For Qt5 in one line:

qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));

For Qt5 for a lot of children, using setUpdatesEnabled():

parentWidget->setUpdatesEnabled(false);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
parentWidget->setUpdatesEnabled(true);

Note that this is not exception safe! While Qt does not at this time appear to throw exceptions here, the signal destroyed() could be connected to code that does throw, or an overridden Object::childEvent(QChildEvent*) could throw.

Better would be to use a helper class:

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));

For Qt4:

QList<QWidget*> childWidgets = parentWidget->findChildren<QWidget*>();
foreach(QWidget* widget, childWidgets)
    if (widget->parentWidget() == parentWidget)
        delete widget;

Removing from the QLayout works in both Qt4 and Qt5:

QLayoutItem* child;
while (NULL != (child = layout->takeAt(0))) // or nullptr instead of NULL
    delete child;

QObjects (and therefore QWidgets) remove themselves (automagically) from their parent in their (QObject) destructor.

月下凄凉 2024-10-05 02:27:19

来自 Qt docs

以下代码片段显示了删除所有项目的安全方法从布局:

QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
    ...
    delete child;
}

From Qt docs

The following code fragment shows a safe way to remove all items from a layout:

QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
    ...
    delete child;
}
日记撕了你也走了 2024-10-05 02:27:19

您可以在父小部件类中使用以下内容:

QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
    delete widget;
}

You can use the following in your parent widget class:

QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
    delete widget;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文