Question

Pour un de mes projets que j'ai un arbre de QObject dérivé des objets, qui utilisent la fonctionnalité parent QObject / enfant pour construire l'arbre.

Ceci est très utile, car je utilise des signaux et des machines à sous, utilisez les pointeurs de Qt et gardés attendre les objets parents à supprimer les enfants lorsqu'ils sont supprimés.

Jusqu'à présent, si bon. Malheureusement, maintenant mon projet me oblige à gérer / modifier l'ordre des enfants. QObject ne fournit aucun moyen de changer l'ordre de ses enfants (exception: la fonction raise () de QWidget - mais qui est inutile dans ce cas). Alors maintenant, je suis à la recherche d'une stratégie de contrôle de l'ordre des enfants J'ai eu quelques idées, mais je ne suis pas sûr de leurs avantages et inconvénients.


Option A: index tri personnalisé variable membre

Utilisez une variable membre int m_orderIndex comme une clé de tri et de fournir une méthode de sortedChildren() qui retourne une liste de QObjects triées par cette touche.

  • Facile à mettre en œuvre dans la structure de l'objet existant.
  • Problématiques lorsque la méthode de QObject::children() est outrepassée -. Entraînera des problèmes lors de boucles lorsque l'ordre des éléments est changé, aussi est plus cher que la mise en œuvre par défaut
  • tomberions à l'ordre d'objet QObject si toutes les clés de tri sont égales ou 0 / default.

Option B: Liste redondante des enfants

Maintenir une liste redondante des enfants dans un QList, et ajouter les enfants quand ils sont créés et détruits.

  • nécessite un suivi coûteux ajoutés / supprimés objets. Cela conduit essentiellement à un second suivi des enfants / parents et beaucoup de signaux / slots. QObject fait tout cela en interne déjà, il pourrait ne pas être une bonne idée de le faire à nouveau. se sent aussi comme beaucoup de ballonnement est ajouté pour une chose simple comme changer l'ordre des enfants.
  • Une bonne flexibilité, puisqu'une QList des enfants peut être modifiée au besoin.
  • permet à un enfant d'être dans le QList plus d'une fois, ou pas du tout (même si elle est peut-être encore un enfant du QObject)

Option C: ...

Toutes les idées ou commentaires, en particulier des personnes qui ont déjà résolu ce problème dans leurs propres projets, est très apprécié. Bonne année!

Était-ce utile?

La solution

J'ai passé beaucoup de temps à passer par toutes ces options dans les derniers jours et en ont discuté soigneusement avec d'autres programmeurs. Nous avons décidé d'aller pour A .

Chacun des objets que nous gérons est un enfant d'un objet parent. Puisque Qt ne fournit aucun moyen de re-commander ces objets, nous avons décidé d'ajouter une propriété int m_orderIndex à chaque objet, qui est par défaut à 0.

Chaque objet a une fonction accesseur sortedChildren() qui retourne un QObjectList des enfants. Ce que nous faisons dans cette fonction est:

  1. Utilisez la fonction QObject::chilren() normale pour obtenir une liste de tous les objets enfants disponibles.
  2. dynamic_cast tous les objets à notre "classe de base", qui fournit la propriété m_orderIndex.
  3. Si l'objet est coulable, l'ajouter à une liste d'objets temporaires.
  4. Utilisation qSort avec une fonction de LessThan personnalisé pour savoir si qSort a besoin de changer l'ordre de deux objets.
  5. Retour à la liste des objets temporaires.

Nous avons fait cela pour les raisons suivantes:

  • Code existant (en particulier propre code de Qt) peut continuer à utiliser children() sans avoir à se soucier des effets secondaires.
  • Nous pouvons utiliser la fonction children() normale dans des endroits où l'ordre n'a pas d'importance, sans avoir aucune perte de performance.
  • Dans les endroits où nous avons besoin de la liste ordonnée des enfants, nous remplaçons simplement children() par sortedChildren() et obtenir l'effet désiré.

L'une des bonnes choses au sujet de cette approche est que l'ordre des enfants ne change pas si tous les indices de tri sont mis à zéro.

Désolé pour répondre à ma propre question, l'espoir que les gens avec le éclaire même problème. ;)

Autres conseils

Qu'en est-il quelque chose comme ...

  1. QList ListChildren = (QList) enfants ();
  2. trier ListChildren
  3. foreach ListChildren setParent (TempParent)
  4. foreach ListChildren setParent (OriginalParent)

Un hack méchant: QObject :: enfants () retourne une référence -à-const. Vous pouvez rejetterai la const-ness et manipuler ainsi la liste interne directement.

est assez mal cependant, et a le risque de vicier itérateurs qui QObject maintient en interne.

Je n'ai pas une option séparée C, mais en comparant l'option A et B, vous parlez ~ 4 octets (pointeur 32 bits, nombre entier de 32 bits) dans les deux cas, alors je partirais avec l'option B, comme vous pouvez garder cette liste triée.

Pour éviter la complexité supplémentaire des enfants de suivi, vous pouvez tricher et garder votre liste triée et bien rangé, mais le combiner avec une méthode sortedChildren qui filtre tous les non-enfants. La complexité sage, ce aught pour mettre fin autour de O (nlogm) (n = enfants, m = entrées de la liste, en supposant que m> = n, à savoir les enfants sont toujours ajoutés) à moins que vous avez un grand revirement sur les enfants. Appelons cette option C.

Quicksort, dans votre option Suggéré A, vous donne O (n2) (wc), mais exige également que pour récupérer les pointeurs, les tracer, retreive un entier, etc. La méthode combinée n'a besoin que d'une liste des pointeurs (aught pour être O (n)).

J'ai eu le même problème et je l'ai résolu par l'option B. Le suivi est pas difficile, il suffit de créer une méthode « addChild void (type * ptr); » et un autre pour supprimer un childitem.

Vous ne souffrez pas de redondance du mal si vous stockez exclusivly les enfants dans le childlist privé / public (QList) de chaque élément et déposez la base QObject. Son assez facile à mettre en œuvre sans auto-enfant gratuit (mais qui nécessite un pointeur parent supplémentaire).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top