我尝试从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删除项目.有任何想法吗?
解决方法
注意:如果您只是寻找一个快速解决这个问题,那么只需使用下面提供的代码.如果您对网格布局中行列处理的背景和困难感兴趣,请继续阅读.
关于QGridLayout行和列
首先,请注意rowCount()和columnCount()返回内部分配的行和列数.例如,如果在新构造的网格布局上调用addWidget(widget,5,7),则行计数将为6,列计数将为8,并且除了行索引5之外的单元格的网格布局的所有单元格并且列索引7将为空,因此在GUI内不可见.
请注意,不可能从网格布局中删除这样的内部行或列.换句话说,网格布局的行和列计数因此总是只能增长,但不会缩小.
您可以做的是删除特定行或列的单元格的内容,这将有效地与删除行或列本身具有相同的效果.但是请注意,这不会更改任何行或列计数,也不会更改任何行或列索引.
清除行或列
那么一行或一列的内容怎么能被清除?这不幸也不像看起来那么容易.
首先,您需要考虑如果您只想从布局中删除小部件,或者您还希望将其删除.如果您仅从布局中删除小部件,则可以将它们重新放入不同的布局,或者手动给它们一个合理的几何体. (请注意,如果不这样做,这些小部件将只会在当前位置保持可见,这几乎绝对不是您想要的.)如果小部件也被删除,它们将从GUI中消失.下面提供的代码使用一个布尔参数来控制小部件删除.
接下来,我们必须考虑一个布局单元格不能只包含一个窗口小部件,而且还包含嵌套布局,其本身可以包含嵌套布局等等.我们还需要处理跨越多行和列的布局项.最后,还有一些行和列属性,如最小宽度和高度,不依赖于单元格内容,但仍然必须重置.
把它放在一起 – 代码
使用下面的removeRow()和removeColumn()函数从网格布局中删除一行或一列.
/** * 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(); } /** * 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,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,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,column,deleteWidgets); layout->setColumnMinimumWidth(column,0); layout->setColumnStretch(column,0); }