从QGridLayout中删除窗口小部件 [英] Removing widgets from QGridLayout

查看:227
本文介绍了从QGridLayout中删除窗口小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试从 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;
    }
}

但是当我调用它时,应用程序崩溃与SIGSEGV在删除项在第一次迭代。任何想法?

But when I call it, the app crashes with SIGSEGV on delete item in the first iteration. Any ideas?

推荐答案

注意:如果您只是想快速解决这个问题,然后只需使用下面提供的代码。如果您对网格布局中行和列处理的背景和困难感兴趣,请继续阅读。

Note: If you're just looking for a quick fix for this problem, then simply use the code which is provided below. If you're interested in the backgrounds and difficulties of row and column handling in grid layouts, then read on.

首先,注意 rowCount() columnCount() strong>内部分配行和列。例如,如果在新构造的网格布局上调用 addWidget(widget,5,7),则行计数为6,列数为8,除了行索引5和列索引7上的单元格之外的网格布局的所有单元格将是空的,因此在GUI内不可见。

First, note that rowCount() and columnCount() return the number of internally allocated rows and columns. As an example, if you call 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 row index 5 and column index 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 thus always only grow, but never shrink.

您可以做的是删除特定行或列的单元格的内容,这将有效地具有与删除行或列本身相同的效果。

What you can do is to remove the contents of the cells of a specific row or column, which will effectively have the same effect as removing the row or column itself. Note, however, that this will neither change any row or column count nor any row or column indices.

那么如何清除行或列的内容呢?这不幸也不像看起来那么容易。

So how can the contents of a row or column be cleared? This unfortunately also isn't as easy as it might seems.

首先,你需要考虑如果你只想从布局中移除小部件 / strong>,或者您还希望它们被删除。如果只从布局中删除窗口小部件,则可以稍后将它们放回不同的布局,或手动给它们一个合理的几何体。 (注意,如果你不这样做,这些小部件将仅仅保持在它们当前位置可见,这几乎肯定不是你想要的。)如果小部件也被删除,它们将从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 can put them back into a different layout afterwards or manually give them a reasonable geometry. (Note that if you don't do that, the widgets will simply keep visible at their current position, which is almost certainly not what you want.) If the widgets also become deleted, they will disappear from the GUI. The code provided below uses a boolean parameter to control widget deletion.

接下来,我们必须考虑一个布局单元格不能只包含一个窗口小部件, strong>嵌套布局,它本身可以包含嵌套布局,等等。我们还需要处理跨越多行和多列的布局项。最后,有一些行和列属性,例如最小宽度和高度,它们不依赖于单元格内容,但仍然必须重置。

Next, we 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. We 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 cell contents but still have to be reset.

使用 removeRow()

/**
 * 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, 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);
}

这篇关于从QGridLayout中删除窗口小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆