Domanda

Per uno dei miei progetti ho un albero di QObject derivato oggetti, che utilizzano la funzionalità padre / figlio di QObject per costruire l'albero.

Questo è molto utile, dal momento che io faccio uso di segnali e slot, utilizzare i puntatori custoditi di Qt e aspetto oggetti padre di eliminare i bambini quando vengono cancellati.

Fin qui tutto bene. Purtroppo ora il mio progetto mi impone di gestire / modificare l'ordine dei bambini. QObject non fornisce alcun mezzo di cambiare l'ordine dei suoi figli (eccezione: la funzione di QWidget raise () - ma questo è inutile in questo caso). Così ora sto cercando una strategia di controllare l'ordine dei bambini Ho avuto un paio di idee, ma non sono sicuro circa i loro pro e contro:.


Opzione A: ordinamento personalizzato variabile membro index

Utilizzare una variabile membro int m_orderIndex come chiave di ordinamento e di fornire un metodo sortedChildren() che restituisce un elenco di QObject ordinati per questa chiave.

  • Facile da implementare nella struttura oggetto esistente.
  • problematico quando il metodo QObject::children() viene sovrascritto -. Porterà a problemi durante i cicli quando l'ordine gli elementi è cambiato, è anche più costoso di implementazione di default
  • dovrebbe cadere di nuovo a oggetto ordine QObject se tutte le chiavi di ordinamento sono uguali o 0 / default.

Opzione B: lista ridondante dei bambini

Mantenere una lista ridondante di bambini in un QList, e aggiungere i bambini ad essa quando vengono creati e distrutti.

  • Richiede costoso inseguimento degli oggetti aggiunti / cancellati. Questo porta in fondo ad un secondo / tracking genitore bambino e molti segnali / slot. QObject fa tutto questo internamente già, quindi potrebbe non essere una buona idea di farlo di nuovo. sente anche come si aggiunge un sacco di gonfiare per una cosa semplice come la modifica dell'ordine dei bambini.
  • Buona flessibilità, dal momento che un QList dei bambini può essere modificato in base alle esigenze.
  • Consente a un bambino di essere in QList più di una volta, o per niente (anche se potrebbe essere ancora un bambino del QObject)

Opzione C:? ...

Tutte le idee o suggerimenti, in particolare da parte di persone che hanno già risolto questo nei propri progetti, è molto apprezzato. Felice anno nuovo!

È stato utile?

Soluzione

Ho passato un sacco di tempo a passare attraverso tutte queste opzioni nei giorni scorsi e discusso con cura con alcuni altri programmatori. Abbiamo deciso di andare per A .

Ogni degli oggetti che stanno gestendo è un figlio di un oggetto padre. Dal momento che Qt non fornisce alcun mezzo di ri-ordinare questi oggetti, abbiamo deciso di aggiungere una proprietà int m_orderIndex a ciascun oggetto, che per default è 0.

Ogni oggetto ha una funzione sortedChildren() di accesso che restituisce una QObjectList dei bambini. Quello che facciamo in questa funzione è:

  1. Utilizzare la funzione QObject::chilren() normale per ottenere un elenco di tutti gli oggetti a disposizione del bambino.
  2. dynamic_cast tutti gli oggetti per la nostra "classe di base", che fornisce la proprietà m_orderIndex.
  3. Se l'oggetto è calcinabile, aggiungerlo a una lista oggetto temporaneo.
  4. uso qSort con una funzione di LessThan personalizzata per scoprire se qsort ha bisogno di cambiare l'ordine dei due oggetti.
  5. Restituisce la lista oggetto temporaneo.

L'abbiamo fatto per i seguenti motivi:

  • codice (in particolare proprio codice di Qt) esistenti possono continuare a utilizzare children(), senza doversi preoccupare di effetti collaterali.
  • Siamo in grado di utilizzare la funzione di children() normale in luoghi in cui l'ordine non importa, senza avere alcuna perdita di prestazioni.
  • Nei luoghi in cui abbiamo bisogno l'elenco ordinato dei bambini, abbiamo semplicemente sostituire children() da sortedChildren() e ottenere l'effetto desiderato.

Una delle cose buone di questo approccio è, che l'ordine dei bambini non cambia se tutti gli indici di ordinamento sono impostati a zero.

Ci scusiamo per rispondere alla mia domanda, la speranza che illumina le persone con lo stesso problema. ;)

Altri suggerimenti

Che dire qualcosa di simile ...

  1. QList ListChildren = (QList) figli ();
  2. sorta ListChildren
  3. foreach ListChildren setParent (TempParent)
  4. foreach ListChildren setParent (OriginalParent)

Una brutta mod: QObject :: bambini () restituisce un riferimento -to-cost. Si potrebbe gettare via il const-ness e quindi manipolare la lista interna direttamente.

Questo è abbastanza male, però, e ha il rischio di iteratori invalidanti che QObject mantiene internamente.

Non ho un'opzione C separato, ma confrontando l'opzione A e B, si sta parlando ~ 4 byte (puntatore a 32 bit, 32 bit integer) in entrambi i casi, quindi mi piacerebbe andare con l'opzione B, come è possibile mantenere tale elenco ordinato.

Per evitare la complessità aggiuntiva di monitoraggio dei bambini, si potrebbe imbrogliare e mantenere la lista ordinata e ordinato, ma combinarlo con un metodo sortedChildren che filtra tutti i non-bambini. Complessità saggio, questo alcunché per finire intorno O (nlogm) (n = bambini, m = Lista voci, assumendo che m> = n, vale a dire i bambini sono sempre aggiunti) a meno che non si dispone di una grande inversione di tendenza sui bambini. Chiamiamo questa opzione C.

Quicksort, nella vostra opzione ha suggerito una, vi dà O (n2) (wc), ma richiede anche di retreive puntatori, li traccia, retreive un intero, ecc Il metodo combinato ha bisogno solo di un elenco dei puntatori (aught per essere O (n)).

Ho avuto lo stesso problema e ho risolto da Opzione B. tracciamento non è poi così difficile, basta creare un metodo di "vuoto addChild (tipo * ptr);" e un altro per eliminare un childitem.

Non si soffre di ridondanza male se si exclusivly memorizzano i bambini all'interno della childlist privato / pubblico (QList) di ogni ordinale e rilasciare la base QObject. Il suo in realtà abbastanza facile da implementare auto-figlio-di punizione sulla libera (anche se questo richiede un puntatore genitore extra).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top