Удаление QWidgets из QGridLayout

У меня есть QGridLayout, куда я добавляю свой собственный QWidgets.

Когда я пытаюсь удалить их все, они якобы удаляются из макета (поскольку функция layout.count() возвращает 0), но они все еще отображаются в интерфейсе, и я могу с ними взаимодействовать.

Вот как я добавляю виджеты:

void MyClass::addCustomWidget(CustomWidget *_widget, int r, int c)
{
    layout->addWidget(_widget, r, c);
    _widget->show();
}

И вот как я их удаляю:

void MyClass::clearLayout()
{
    qDebug() << "Layout count before clearing it: " << layout->count();

    int count = layout->count();
    int colums = layout->columnCount();
    int rows = layout->rowCount();

    int i=0;
    for(int j=0; j<rows; j++)
    {
        for(int k=0; k<colums && i<count; k++)
        {
            i++;

            qDebug() << "Removing item at: " << j << "," << k;
            QLayoutItem* item = layout->itemAtPosition(j, k);

            if (!item) continue;

            if (item->widget()) {
                layout->removeWidget(item->widget());
            } else {
                layout->removeItem(item);
            }
            qDebug() << "Removed!";
        }
    }

    qDebug() << "Layout count after clearing it: " << layout->count();
}

Любая помощь или совет по правильному удалению элементов/виджетов из QGridLayout?

П.Д. : Я видел в Интернете, что многие люди удаляют виджет напрямую (delete _widget) после удаления их из макета. В моем случае это невозможно, так как мне нужно хранить эти виджеты в памяти.


person azorrozua    schedule 23.05.2012    source источник
comment
возможный дубликат удаления виджетов из QGridLayout   -  person emkey08    schedule 09.10.2013


Ответы (4)


Просто быть чистым. Вы не "удаляли" виджеты. Вы только удалили их из макета. Удаление из макета означает только то, что виджет больше не будет управляться (изменяться в размере/позиционироваться) этим макетом, НО это не означает, что виджет будет "удален" (как C++). Также виджет не будет волшебным образом скрыт. Ваш виджет после удаления из макета по-прежнему остается в виджете, в котором он был создан/управлялся. Таким образом, владелец этого макета по-прежнему имеет этот виджет как дочерний (видимый дочерний).

Вы должны

  1. скрыть виджет или если вы уверены, что он больше не будет использоваться

  2. удалить виджет с ключевым словом «удалить»

Также вам не нужно вызывать removeWidget(item->widget()); removeItem(item) будет достаточно для всех элементов макета (даже тех, у которых есть виджет внутри)

person Kamil Klimek    schedule 23.05.2012
comment
Мое намерение состоит в том, чтобы удалить виджеты из макета (и больше не показывать их), но сохранить их в памяти. Я попытался скрыть виджеты (_widget.hide), прежде чем удалить их из макета, и это сработало, спасибо. - person azorrozua; 23.05.2012

Пытаться

QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0);

Это должно быть безопасным. Если по каким-либо причинам это не работает, вы можете использовать коллекцию виджетов или элементов макета, которая обновляется каждый раз, когда вы добавляете виджет. Затем, чтобы удалить цикл в коллекции и удалить каждый элемент из макета.

person UmNyobe    schedule 23.05.2012

Вы также можете использовать deleteLater(), чтобы избежать проблем с сохранением количества дочерних элементов во время итераций:

for (int i = 0; i < gridLayout.count(); i++)
{
   gridLayout.itemAt(i)->widget()->deleteLater();
}
person vdudouyt    schedule 12.03.2017
comment
Спасибо за попытку решить проблему 5 лет спустя ;) - person azorrozua; 13.03.2017

Ни один из этих ответов не работал для меня. В моей ситуации у меня есть несколько объектов, каждый со своим QChartView. Идея состоит в том, что пользователь выбирает, какой объект он хочет просмотреть, и центральная общая область в главном окне обновляется с помощью QChartView выбранного пользователем объекта. Это должно было быть просто: просто удалите виджет из области графика и добавьте новый. Что в итоге сработало для меня, так это:

while( QLayoutItem* item = ui->mPlotArea->layout()->takeAt(0) )
{
    item->widget()->setVisible(false);
    ui->mPlotArea->layout()->removeItem(item);
}

ui->mPlotArea->layout()->addWidget( pv );
pv->setVisible(true);

Где mPlotArea — это QFrame, а pv — производный класс от QChartView. Я не могу объяснить, почему другие ответы не сработали, но я потратил пару часов, пробуя разные виджеты и разные способы удаления без удаления, организации и т. Д.

person Alex Baum    schedule 01.10.2020