qgridlayoutからウィジェットを削除します
-
28-10-2019 - |
質問
指定された行からウィジェットを削除しようとします 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
最初の反復で。何か案は?
解決
簡単な回答:以下に示すコードを使用してください
から行または列(または単一のセル)を削除する QGridLayout
トリッキーです。以下に示すコードを使用してください。
長い答え:qgridlayoutの詳細を掘る
まず、それに注意してください QGridLayout::rowCount()
と QGridLayout::columnCount()
常に数を返します 内部的に割り当てられます グリッドレイアウト内の行と列。例として、あなたが電話する場合 QGridLayout::addWidget(widget,5,7)
新たに構築されたグリッドレイアウトでは、行数は6になり、列カウントは8になり、インデックス上のセル(5,7)を除くグリッドレイアウトのすべてのセルは空になり、したがってGUI内で見えます。
残念ながら、残念ながら注意してください 無理だよ グリッドレイアウトからこのような内部行または列を削除するには。言い換えれば、グリッドレイアウトの行と列カウントは常に成長するだけですが、縮小することはありません。
あなたは何 できる 削除することです コンテンツ 行または列の場合、行または列自体を削除するのと同じ視覚効果が効果的になります。しかし、これはもちろん、すべての行と列のカウントとインデックスが 変更されていないまま.
では、行または列(またはセル)の内容をどのようにクリアできますか?残念ながら、これも見た目ほど簡単ではありません。
まず、ウィジェットを削除したい場合は考える必要があります レイアウトから, 、またはあなたもそれらを望んでいる場合 削除されます. 。レイアウトからウィジェットを削除する場合のみ、その後は異なるレイアウトに戻すか、手動で合理的なジオメトリを与えなければなりません。ウィジェットも削除されると、GUIから消えます。提供されたコードは、ブールパラメーターを使用してウィジェットの削除を制御します。
次に、レイアウトセルにはウィジェットだけでなく、 ネストされたレイアウト, 、それ自体がネストされたレイアウトなどを含めることができます。さらに、レイアウトアイテムを処理する必要があります 複数の行と列. 。そして最後に、いくつかの行と列があります 属性 実際の内容に依存しないが、それでも世話をする必要がある最小幅と高さのように。
コード
#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
それ自体が管理しています QLayoutItem
's。私はあなたが電話する瞬間を信じています removeWidget
アイテムは削除されます。したがって、その時点で無効なポインターがあります。それだけでなく、それで何かをしようとしています delete
, 、失敗します。
したがって、削除しないでください、あなたは大丈夫でしょう。