web-dev-qa-db-ja.com

Qt 4でのウィジェットとレイアウトの削除、削除について

(私はQt 4.7、Windows 7、64ビットを使用しています)。

カスタムテーブルを作成しました。各行は、ウィジェットを備えた水平レイアウトです。行は簡単にアクセスできるようにQListに保持され、子も保持されます。行は親ウィジェット内にも追加されます。

親ウィジェットのサイズを変更する場合、新しいサイズを計算し、すべてを削除して、再度作成します。

私の問題は、ウィジェットを削除したくないということです。私がテーブルをクリアしたときだけ、私はそれをします。

QListおよび親レイアウト内にウィジェットがあるため、各行のすべてのウィジェットを削除し、すべてのレイアウトを削除してから、それらを新しいレイアウトに追加するにはどうすればよいですか?

行う場合:各レイアウト内のすべての要素に対してtakeAt(0)ウィジェットを含むQLayoutItemがあります...ウィジェットを削除せずにlayoutItemを削除するにはどうすればよいですか?...ウィジェットを強制終了せずに削除するにはどうすればよいですか?それが親か子かに関係なく?レイアウトにはremoveItem、removeWidget ...のような多くの削除メソッドがありますが、takeWidget ...ではなくtakeAt()だけで、Qlayoutitemを提供します。

いくつかの方法を試しましたが、何が起きてもウィジェットが表示されます。

これに関する質問:

  • ウィジェットはいつ削除されますか?レイアウトからWidget(index)を取得した場合、それ自体でしばらく削除されますか?別のリストにそれへのポインターがある場合、それは起こりますか?

  • removeAt(index)はウィジェットの削除メソッドを実行しますか?

15
darkgaze

OK。うまくいきました。ウィジェットの削除、保持の仕組みを説明しましょう。

ウィジェットは、親レイアウトによって認識されます。そして、レイアウトを介して削除します。行うことにより:

layout()->removeAt(widget);
delete widget;

QLayout(またはその子)でtakeAt(index)を使用すると、QLayoutItemが提供されます。内部のウィジェットにアクセスするには、widget()を使用します。しかし、ウィジェットを削除せずに削除する方法はありません。したがって、このアプローチは無効です。

ドキュメントでは、要素を削除する方法を示します:

QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0)  {
    ...
    delete child;
}

Qtで注意すべき特別なことは次のとおりです:レイアウトの階層ツリーがある場合、どのくらい深くてもレイアウト内にaddLayout()で追加されますウィジェットが挿入されます。子レイアウトまたは親レイアウトからツリーパスを削除することができます。子レイアウトから。

最も簡単なのは、すべてのアイテムへのポインターのリストをカスタムテーブルに保持することです。テーブルをクリアして再構築するときは、ウィジェット内でこれを行うだけです。

  CustomTableItem* item;
  while ( !items_.isEmpty() && ( (item = items_.takeFirst()) != 0 ) ){
    layout()->removeWidget(item);
    delete item; // It works no matter where the item is
  }

  items_.clear(); // clear the list afterwards.

そして、それは完全に機能し、それ自体でレイアウトも更新します。要素を保持する場合は、「アイテムの削除」をスキップします。後で使用します。

注意すべき重要なことは、異なる「削除」関数が異なる動作をすることです(Qt Docsで理解しているように)QListまたは同様のウィジェットとQLayoutで。

QListでは、removeAtは実際にオブジェクトを削除します。

(Qt 4.7 QList Docs)「インデックス位置iのアイテムを削除します。iはリスト内の有効なインデックス位置でなければなりません(つまり、0 <= i <size())。」

QLayoutでは、removeWidgetまたはremoveItemはアイテム/ウィジェットを削除しません。以前のように、あなたはそれを削除する責任があります。

(Qt 4.7 QLayout Docs)「ウィジェットウィジェットをレイアウトから削除します。この呼び出しの後、ウィジェットに適切なジオメトリを与えるか、ウィジェットをレイアウトに戻すのは呼び出し側の責任です。」

それが役に立てば幸い。エラーが表示された場合は、教えていただければ回答を編集します。

ここでの削除の詳細: その他のスタックオーバーフローの投稿

25
darkgaze

Qtのウィジェットは通常のC++オブジェクトであり、C++ delete演算子を使用して他のオブジェクトと同様に削除できます。

_delete myWidget;
_

Qtでは、ウィジェット間には常に親子関係があります。親ウィジェットが破棄されると、すべての子が削除されます。通常、トップレベルのウィジェット、つまりウィンドウとダイアログ以外のウィジェットを明示的に削除することを考慮する必要はありません。 Qtは子ウィジェットを削除します。

QList::removeAt(int)は、削除されるオブジェクトを削除せず、リストからオブジェクトを削除するだけです。オブジェクトも削除したい場合は、次のようにする必要があります。

_delete myList.takeAt(0);
_

これは、removeAt(int)takeAt(int)takeFirst()などのすべての関数に適用されます。オブジェクトを削除することはなく、コンテナ(リスト、レイアウト、 scrollareaなど)。ほとんどの場合、ウィジェットの所有権は呼び出し元に移されます(親子関係が壊れると、呼び出し元がウィジェットを削除する責任を負うことになります)が、常にそうであると想定せず、常に関数のドキュメントを読んでください。

6
Daniel Hedberg