コンストラクターQWidget(QWidget *parent)
を使用しています。この親ウィジェットには、多くの子ウィジェットが含まれています。実行時に親からすべての子ウィジェットをクリアする必要があります。これどうやってするの?
前の答えは間違っています!! Qt4のfindChildren
再帰的には子をリストするため、findChildren
を使用してウィジェットの子を削除することはできません。したがって、子の子を削除します。その後、子が2回削除され、アプリがクラッシュする可能性があります。
より一般的には、Qtでは、QObject
ポインターのリストを取得し、それらを1つずつ削除することは危険です。オブジェクトを破棄すると、親の所有権メカニズムのため、またはdestroyed()
信号をdeleteLater()
スロットに送信します。したがって、リストの最初のオブジェクトを破棄すると、次のオブジェクトが無効になる可能性があります。
次のいずれかの方法で子ウィジェットを一覧表示する必要があります。
@galinetteによって指摘された再帰性の問題に対処するには、whileループでウィジェットを削除するだけです。
while ( QWidget* w = findChild<QWidget*>() )
delete w;
要約と補足:
1行のQt5の場合:
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
多くの子のQt5の場合、setUpdatesEnabled()を使用します。
parentWidget->setUpdatesEnabled(false);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
parentWidget->setUpdatesEnabled(true);
これは例外安全ではないことに注意してください!現時点では、Qtはここで例外をスローするようには見えませんが、destroyed()シグナルは、スローするコードに接続されているか、オーバーライドされた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(したがってQWidgets)は、(QObject)デストラクタで親から(自動的に)自分自身を削除します。
Qtから docs
次のコードフラグメントは、レイアウトからすべてのアイテムを削除する安全な方法を示しています。
QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
...
delete child;
}