コンストラクタを使用していQWidget(QWidget *parent)
ます。この親ウィジェットには、多くの子ウィジェットが含まれています。実行時に親からすべての子ウィジェットをクリアする必要があります。これどうやってするの?
5 に答える
前の答えは間違っています!! Qt4 は子を再帰的にリストfindChildren
するため、ウィジェットの子を削除するために使用することはできません。したがって、子の子を削除すると、子が 2 回削除され、アプリがクラッシュする可能性があります。findChildren
より一般的に言えば、Qt では、ポインターのリストを取得して 1 つずつ削除することは危険です。オブジェクトを破棄すると、親の所有権メカニズムにより、またはシグナルをスロットにQObject
接続することによって、他のオブジェクトが連鎖的に破棄される可能性があるためです。したがって、リスト内の最初のオブジェクトを破棄すると、次のオブジェクトが無効になる場合があります。destroyed()
deleteLater()
次のいずれかの方法で、子ウィジェットをリストする必要があります。
- Qt5 を使用している場合は、Qt::FindDirectChildrenOnly フラグを findChild に渡します (質問されたときには存在しませんでした...)。
- アイテムのリストに QLayout 関数を使用し、
- QObject::children を使用し、isWidgetType() またはキャストを使用してウィジェットであるかどうかをテストするたびに
- ループで findChild() を使用し、null ポインターが返されるまで結果を削除します
@galinette によって指摘された再帰性の問題に対処するには、while ループでウィジェットを削除するだけです。
while ( QWidget* w = findChild<QWidget*>() )
delete w;
要約と補足:
1行でQt5の場合:
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
setUpdatesEnabled() を使用して、多くの子供向けの Qt5 の場合:
parentWidget->setUpdatesEnabled(false);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
parentWidget->setUpdatesEnabled(true);
これは例外セーフではないことに注意してください。現時点で Qt はここで例外をスローするようには見えませんが、シグナル destroy() がスローするコードに接続されているか、オーバーライドされた Object::childEvent(QChildEvent*) がスローされる可能性があります。
ヘルパー クラスを使用することをお勧めします。
class UpdatesEnabledHelper
{
QWidget* m_parentWidget;
public:
UpdatesEnabledHelper(QWidget* parentWidget) : m_parentWidget(parentWidget) { parentWidget->setUpdatesEnabled(false); }
~UpdatesEnabledHelper() { m_parentWidget->setUpdatesEnabled(true); }
};
...
UpdatesEnabledHelper helper(parentWidget);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
Qt4 の場合:
QList<QWidget*> childWidgets = parentWidget->findChildren<QWidget*>();
foreach(QWidget* widget, childWidgets)
if (widget->parentWidget() == parentWidget)
delete widget;
QLayout からの削除は、Qt4 と Qt5 の両方で機能します。
QLayoutItem* child;
while (NULL != (child = layout->takeAt(0))) // or nullptr instead of NULL
delete child;
QObject (および QWidget) は、(QObject) デストラクタで親から (自動的に) 自分自身を削除します。
Qtドキュメントから
次のコード フラグメントは、レイアウトからすべての項目を安全に削除する方法を示しています。
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child;
}
親ウィジェットクラスでは、次を使用できます。
QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
delete widget;
}