web-dev-qa-db-fra.com

À propos de la suppression, de la suppression de widgets et de mises en page dans Qt 4

(J'utilise Qt 4.7, Windows 7, 64 bits).

J'ai créé une table personnalisée. Chaque ligne est une disposition horizontale avec des widgets. Les rangées sont conservées dans une QList pour un accès facile, et les enfants aussi. Les lignes sont également ajoutées à l'intérieur du widget parent.

Si je redimensionne le widget parent, je calcule les nouvelles tailles, supprime tout et le recrée à nouveau.

Mon problème est que je ne veux supprimer aucun widget. Ce n'est que lorsque j'efface la table que je le fais.

Étant donné que j'ai les widgets dans une liste Q et dans les dispositions parent, comment puis-je supprimer tous les widgets de chaque ligne, supprimer toutes les dispositions, puis les ajouter à de nouvelles dispositions?

Si je le fais: takeAt (0) pour chaque élément à l'intérieur de chaque mise en page, j'ai un QLayoutItem avec un widget à l'intérieur ... Comment puis-je supprimer le layoutItem sans supprimer le widget? .... Comment supprimer le widget sans le tuer, peu importe si c'est chez le parent ou l'enfant? Parce qu'il existe de nombreuses méthodes pour supprimer: removeItem, removeWidget ... dans une mise en page, mais pas takeWidget ... il suffit de takeAt () et cela donne un Qlayoutitem.

J'ai essayé plusieurs façons, mais je vois toujours les widgets, peu importe ce qui leur est arrivé.

Questions à ce sujet:

  • Quand un widget est-il supprimé? Si je prends Widget (index) d'une mise en page, est-il supprimé quelque temps par lui-même? cela se passe-t-il si j'ai un pointeur vers lui dans une autre liste?

  • removeAt (index) exécute-t-il la méthode de suppression d'un widget?

15
darkgaze

D'accord. Je l'ai fait fonctionner. Permettez-moi de vous expliquer comment cette suppression, la conservation des widgets fonctionne.

Un widget est connu par sa disposition parent. Et vous le supprimez via la mise en page. En faisant:

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

Si vous utilisez takeAt (index) dans un QLayout (ou ses enfants), il vous donne un QLayoutItem. Pour accéder au widget à l'intérieur, utilisez simplement widget (). Mais il n'y a aucun moyen de supprimer le widget sans le supprimer. Cette approche n'est donc pas valide.

Dans les documents, il indique un moyen de supprimer les éléments:

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

Une chose spéciale à noter dans Qt est la suivante: si vous avez une arborescence de hiérarchies , ajoutée avec addLayout () à l'intérieur des dispositions, quelle que soit la profondeur votre widget est inséré, vous pouvez le supprimer des dispositions enfant ou de l'une des dispositions parent , si le chemin de l'arborescence de la disposition et de cet élément est construit des mises en page des enfants.

Le plus simple est de conserver une liste de pointeurs vers tous les éléments, dans un tableau personnalisé. Lorsque vous effacez le tableau pour le reconstruire, faites-le dans votre widget:

  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.

Et cela fonctionne parfaitement, met également à jour la mise en page. Si vous souhaitez conserver les éléments, sautez simplement la "suppression de l'élément"; et utilisez-les ensuite.

Une chose importante à noter est que différentes fonctions de "suppression" fonctionnent différemment (comme je le comprends sur Qt Docs) dans QList ou des widgets similaires, et dans un QLayout .

Dans la QList, removeAt supprime réellement l'objet.

(Qt 4.7 QList Docs) "Supprime l'élément à la position d'index i. I doit être une position d'index valide dans la liste (c'est-à-dire 0 <= i <size ())."

Dans un QLayout, removeWidget ou removeItem ne supprime pas l'élément/widget, vous avez la responsabilité de le supprimer, comme je l'ai fait auparavant.

(Qt 4.7 QLayout Docs) "Supprime le widget widget de la mise en page. Après cet appel, il est de la responsabilité de l'appelant de donner au widget une géométrie raisonnable ou de remettre le widget dans une mise en page."

J'espère que cela aide. Si vous voyez une erreur, vous pouvez me le dire et je modifierai la réponse!

Plus d'informations sur la suppression ici: Autre post stackoverflow

25
darkgaze

Un widget dans Qt est un objet C++ normal et peut être supprimé avec l'opérateur C++ delete comme tout autre objet:

delete myWidget;

Dans Qt, il y a toujours une relation parent-enfant entre les widgets. Lorsque le widget parent est détruit, il supprimera tous ses enfants. En général, vous n'avez pas besoin de penser à supprimer explicitement des widgets, mais les widgets de niveau supérieur, c'est-à-dire les fenêtres et les boîtes de dialogue. Qt se chargera de supprimer tous les widgets enfants.

QList::removeAt(int) ne supprime pas l'objet qui est supprimé, il supprime uniquement l'objet de la liste. Si vous souhaitez également supprimer l'objet, vous devrez faire quelque chose comme:

delete myList.takeAt(0);

Cela s'applique à toutes les fonctions telles que removeAt(int), takeAt(int), takeFirst(), etc. Ils ne suppriment jamais les objets, ils les suppriment uniquement du conteneur (liste, mise en page, scrollarea, etc.). Dans la plupart des cas, la propriété du widget est ensuite transférée à l'appelant (l'appelant devient responsable de la suppression du widget lorsque la relation parent-enfant se rompt), mais ne supposez pas que c'est toujours le cas, lisez toujours la documentation de la fonction .

6
Daniel Hedberg