Удаление виджетов из QGridLayout
Я пытаюсь удалить виджеты из указанной строки QGridLayout
такой:
void delete_grid_row(QGridLayout *layout, int row)
{
if (!layout || row < 0) return;
for (int i = 0; i < layout->columnCount(); ++i) {
QLayoutItem* item = layout->itemAtPosition(row, i);
if (!item) continue;
if (item->widget()) {
layout->removeWidget(item->widget());
} else {
layout->removeItem(item);
}
delete item;
}
}
но когда я называю его, приложение падает с SIGSEGV на delete item
в первой итерации. Есть идеи?
2 ответов
короткий ответ:
удаление строки или столбца QGridLayout
сложно. Используйте removeRow()
и removeColumn()
функции из кода, приведенного ниже.
/**
* Removes all layout items on the given @a row from the given grid
* @a layout. If @a deleteWidgets is true, all concerned child widgets
* become not only removed from the layout, but also deleted. Note that
* this function doesn't actually remove the row itself from the grid
* layout, as this isn't possible (i.e. the rowCount() and row indices
* will stay the same after this function has been called).
*/
void removeRow(QGridLayout *layout, int row, bool deleteWidgets) {
remove(layout, row, -1, deleteWidgets);
layout->setRowMinimumHeight(row, 0);
layout->setRowStretch(row, 0);
}
/**
* Removes all layout items on the given @a column from the given grid
* @a layout. If @a deleteWidgets is true, all concerned child widgets
* become not only removed from the layout, but also deleted. Note that
* this function doesn't actually remove the column itself from the grid
* layout, as this isn't possible (i.e. the columnCount() and column
* indices will stay the same after this function has been called).
*/
void removeColumn(QGridLayout *layout, int column, bool deleteWidgets) {
remove(layout, -1, column, deleteWidgets);
layout->setColumnMinimumWidth(column, 0);
layout->setColumnStretch(column, 0);
}
/**
* Helper function. Removes all layout items within the given @a layout
* which either span the given @a row or @a column. If @a deleteWidgets
* is true, all concerned child widgets become not only removed from the
* layout, but also deleted.
*/
void remove(QGridLayout *layout, int row, int column, bool deleteWidgets) {
// We avoid usage of QGridLayout::itemAtPosition() here to improve performance.
for (int i = layout->count() - 1; i >= 0; i--) {
int r, c, rs, cs;
layout->getItemPosition(i, &r, &c, &rs, &cs);
if ((r <= row && r + rs - 1 >= row) || (c <= column && c + cs - 1 >= column)) {
// This layout item is subject to deletion.
QLayoutItem *item = layout->takeAt(i);
if (deleteWidgets) {
deleteChildWidgets(item);
}
delete item;
}
}
}
/**
* Helper function. Deletes all child widgets of the given layout @a item.
*/
void deleteChildWidgets(QLayoutItem *item) {
if (item->layout()) {
// Process all child items recursively.
for (int i = 0; i < item->layout()->count(); i++) {
deleteChildWidgets(item->layout()->itemAt(i));
}
}
delete item->widget();
}
длинный ответ: подробности об этом
во-первых, обратите внимание, что QGridLayout::rowCount()
и QGridLayout::columnCount()
всегда возвращает число внутренне выделено строки и столбцы в макете сетки. В качестве примера, если вы вызываете QGridLayout::addWidget(widget,5,7)
на недавно построенном макете сетки количество строк будет равно 6, а столбец количество будет 8, и все ячейки макета сетки, кроме ячейки по индексу (5,7), будут пустыми и, следовательно, невидимыми в GUI.
обратите внимание, что это, к сожалению,невозможно удалить такую внутреннюю строку или столбец из макета сетки. Другими словами, количество строк и столбцов макета сетки всегда может только расти, но никогда не сжиматься.
что ты can снять содержимое ячейки строки или столбца, которые будут эффективно имеют тот же визуальный эффект, что и удаление самой строки или столбца. Но это, конечно, означает, что все подсчеты строк и столбцов и индексы будут остаются неизменными.
Итак, как можно очистить содержимое строки или столбца? К сожалению, это не так просто, как может показаться.
во-первых, вам нужно подумать, если вы хотите удалить только виджеты из макета, или если вы также хотите, чтобы они стать удалено. Если вы только удалите виджеты из макета, вы должны поместить их обратно в другой макет после этого или вручную дать им разумную геометрию. Если виджеты также будут удалены, они исчезнут из GUI. Предоставленный код использует логический параметр для управления удалением виджета.
Далее, вы должны учитывать, что ячейка макета может содержать не только виджет, но и вложенный макет, который сам может содержать вложенные макеты, и так далее. Вам также нужно обрабатывать элементы макета, которые охватывают несколько строк и столбцов. И, наконец, есть некоторые строки и столбцы атрибуты как минимум, ширины и высоты, которые не зависят от фактического содержимого ячейки, но все равно придется заботиться.
на управление QLayoutItem
' s. Я верю в тот момент, когда вы звоните removeWidget
элемент будет удален. Таким образом, у вас есть недопустимый указатель в этой точке. Пытаясь сделать что-нибудь с ним, а не просто delete
не получится.
таким образом, просто не удаляйте его, вы будете в порядке.