How to Clear all the Widgets in Parent Widgets?

后端 未结 5 1419
臣服心动
臣服心动 2020-12-17 09:40

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 a

相关标签:
5条回答
  • 2020-12-17 09:44

    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;
    }
    
    0 讨论(0)
  • 2020-12-17 09:45

    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.

    0 讨论(0)
  • 2020-12-17 09:48

    You can use the following in your parent widget class:

    QList<QWidget *> widgets = findChildren<QWidget *>();
    foreach(QWidget * widget, widgets)
    {
        delete widget;
    }
    
    0 讨论(0)
  • 2020-12-17 09:51

    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
    0 讨论(0)
  • 2020-12-17 10:03

    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;
    
    0 讨论(0)
提交回复
热议问题