Удаление 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?
PD: я видел в интернете, что многие люди удаляют виджет напрямую (delete _widget) после удаления их из макета. В моем случае это невозможно, так как мне нужно сохранить эти виджеты в памяти.
4 ответа
Просто быть чистым. Вы не "удалили" виджеты. Вы только удалили их из макета. Удаление из макета означает только то, что виджет больше не будет управляться (изменяться / позиционироваться) этим макетом, НО это не означает, что виджет будет "удален" (в стиле C++). Также виджет не будет магически скрыт. Ваш виджет после удаления из макета все еще остается в виджете, в котором он был создан / которым он управляется. Таким образом, владелец этого макета все еще имеет этот виджет как дочерний (видимый дочерний элемент).
Ты должен
скрыть виджет или если вы уверены, что он больше не будет использоваться
удалить виджет с ключевым словом "удалить"
Также вам не нужно звонить removeWidget(item->widget())
; removeItem(item)
будет достаточно для всех элементов макета (даже для элементов с виджетом внутри)
Вы также можете использовать deleteLater()
чтобы избежать проблем с поддержанием количества детей во время итераций:
for (int i = 0; i < gridLayout.count(); i++)
{
gridLayout.itemAt(i)->widget()->deleteLater();
}
Пытаться
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0);
Это должно быть безопасно. Если по каким-либо причинам это не работает, вы можете использовать коллекцию виджетов или макетов элементов, которая обновляется каждый раз, когда вы добавляете виджет. Затем для удаления вы зациклите коллекцию и удалите каждый элемент из макета.
Ни один из этих ответов не помог мне. В моей ситуации у меня есть несколько объектов, каждый со своим 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
. Я не могу объяснить, почему другие ответы не сработали, но я потратил пару часов, пробуя разные виджеты и разные способы удаления без удаления, организации и т. Д.
Header:
class Grid : QGridLayout
{
public:
Grid(QWidget* parent);
void addElement(QWidget* element, int x, int y);
void delElement(int x, int y);
void resize(int width, int height);
void clear();
protected:
QSize size;
};
void Grid::clear(){
for(int i = 0;i<size.width();i++){
for(int j = 0;j<size.height();j++){
QLayoutItem* item = takeAt(i*size.width() + j);
if(item != NULL) delete item;
}
}
}