問題描述
我嘗試從 QGridLayout
中的指定行中刪除小部件,如下所示:
I try to remove widgets from a specified row in a QGridLayout
like this:
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;
}
}
但是當我調用它時,應用程序在第一次迭代中在 delete item
上崩潰并顯示 SIGSEGV.有什么想法嗎?
But when I call it, the app crashes with SIGSEGV on delete item
in the first iteration. Any ideas?
推薦答案
簡短回答:使用下面提供的代碼
從 QGridLayout
中刪除一行或一列(甚至單個單元格)是很棘手的.使用下面提供的代碼.
Short answer: Use the code provided below
Removing a row or column (or even a single cell) from a QGridLayout
is tricky. Use the code provided below.
首先,請注意QGridLayout::rowCount()
和QGridLayout::columnCount()
總是返回內部分配 的行數和網格布局中的列.例如,如果您在新構建的網格布局上調用 QGridLayout::addWidget(widget,5,7)
,則行數將為 6,列數將為 8,并且所有單元格除了索引 (5,7) 上的單元格之外的網格布局將為空,因此在 GUI 中不可見.
First, note that QGridLayout::rowCount()
and QGridLayout::columnCount()
always return the number of internally allocated rows and columns in the grid layout. As an example, if you call QGridLayout::addWidget(widget,5,7)
on a freshly constructed grid layout, the row count will be 6 and the column count will be 8, and all cells of the grid layout except the cell on index (5,7) will be empty and thus invisible within the GUI.
請注意,很遺憾不可能從網格布局中刪除這樣的內部行或列.換句話說,網格布局的行數和列數總是只會增長,而不會縮小.
Note that it's unfortunately impossible to remove such an internal row or column from the grid layout. In other words, the row and column count of a grid layout can always only grow, but never shrink.
您可以做的是刪除行或列的內容,這將有效地具有與刪除行或列本身相同的視覺效果.但這當然意味著所有行和列計數和索引將保持不變.
What you can do is to remove the contents of a row or column, which will effectively have the same visual effect as removing the row or column itself. But this of course means that all row and column counts and indices will remain unchanged.
那么如何清除一行或一列(或單元格)的內容呢?不幸的是,這也并不像看起來那么容易.
So how can the contents of a row or column (or cell) be cleared? This unfortunately also isn't as easy as it might seem.
首先,您需要考慮您是否只想從布局中刪除小部件,或者您是否還希望它們被刪除.如果您只從布局中刪除小部件,則必須在之后將它們放回不同的布局中,或者手動為它們提供合理的幾何形狀.如果小部件也被刪除,它們將從 GUI 中消失.提供的代碼使用布爾參數來控制小部件刪除.
First, you need to think about if you only want to remove the widgets from the layout, or if you also want them to become deleted. If you only remove the widgets from the layout, you must put them back into a different layout afterwards or manually give them a reasonable geometry. If the widgets also become deleted, they will disappear from the GUI. The provided code uses a boolean parameter to control widget deletion.
接下來,您必須考慮到,布局單元不僅可以包含小部件,還可以包含嵌套布局,它本身可以包含嵌套布局,等等.您還需要處理跨越多行和多列的布局項.最后,還有一些行和列的屬性,比如最小寬度和高度,它們不依賴于實際內容,但仍然需要注意.
Next, you have to consider that a layout cell can not just only contain a widget, but also a nested layout, which itself can contain nested layouts, and so on. You further need to handle layout items which span over multiple rows and columns. And, finally, there are some row and column attributes like minimum widths and heights which don't depend on the actual contents but still have to be taken care of.
#include <QGridLayout>
#include <QWidget>
/**
* Utility class to remove the contents of a QGridLayout row, column or
* cell. If the deleteWidgets parameter is true, then the widgets become
* not only removed from the layout, but also deleted. Note that we won't
* actually remove any row or column itself from the layout, as this isn't
* possible. So the rowCount() and columnCount() will always stay the same,
* but the contents of the row, column or cell will be removed.
*/
class GridLayoutUtil {
public:
// Removes the contents of the given layout row.
static void removeRow(QGridLayout *layout, int row, bool deleteWidgets = true) {
remove(layout, row, -1, deleteWidgets);
layout->setRowMinimumHeight(row, 0);
layout->setRowStretch(row, 0);
}
// Removes the contents of the given layout column.
static void removeColumn(QGridLayout *layout, int column, bool deleteWidgets = true) {
remove(layout, -1, column, deleteWidgets);
layout->setColumnMinimumWidth(column, 0);
layout->setColumnStretch(column, 0);
}
// Removes the contents of the given layout cell.
static void removeCell(QGridLayout *layout, int row, int column, bool deleteWidgets = true) {
remove(layout, row, column, deleteWidgets);
}
private:
// Removes all layout items which span the given row and column.
static 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 (
(row == -1 || (r <= row && r + rs > row)) &&
(column == -1 || (c <= column && c + cs > column))) {
// This layout item is subject to deletion.
QLayoutItem *item = layout->takeAt(i);
if (deleteWidgets) {
deleteChildWidgets(item);
}
delete item;
}
}
}
// Deletes all child widgets of the given layout item.
static void deleteChildWidgets(QLayoutItem *item) {
QLayout *layout = item->layout();
if (layout) {
// Process all child items recursively.
int itemCount = layout->count();
for (int i = 0; i < itemCount; i++) {
deleteChildWidgets(layout->itemAt(i));
}
}
delete item->widget();
}
};
這篇關于從 QGridLayout 中刪除小部件的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!