2013-07-17 20 views
10

(utilizzo Qt 4.7, Windows 7, 64 bit).Informazioni sull'eliminazione, rimozione di widget e layout in Qt 4

Ho creato un tavolo personalizzato. Ogni riga è un layout orizzontale con widget. Le file sono mantenute in una lista Q per un facile accesso e anche per i bambini. Le righe vengono anche aggiunte all'interno del widget principale.

Se ridimensiono il widget padre, calcolo le nuove dimensioni, elimina tutto e lo ricrei di nuovo.

Il mio problema è che non voglio cancellare nessun widget. Solo quando cancello il tavolo, lo faccio.

Dato che ho i widget all'interno di una QList e all'interno dei layout principali, come posso rimuovere tutti i widget in ogni riga, eliminare tutti i layout e aggiungerli a nuovi layout?

Se lo faccio: takeAt (0) per ogni elemento all'interno di ogni layout, ho un oggetto QLayoutItem con un widget all'interno ... Come posso cancellare il layoutItem senza eliminare il widget? .... Come rimuovo il widget senza ucciderlo, non importa se è nel genitore o nel bambino? Perché ci sono molti metodi per eliminare: removeItem, removeWidget ... in un layout, ma non takeWidget ... solo takeAt() e dà un Qlayoutitem.

Ho provato diversi modi, ma vedo ancora i widget, non importa cosa gli sia successo.

Domande su questo:

  • Quando parte un widget vengono eliminati? Se prendoWidget (indice) da un layout, viene cancellato un po 'di tempo da solo? succede se ho un puntatore ad esso in un'altra lista?

  • removeAt (index) esegue il metodo di eliminazione di un widget?

risposta

19

Ok. Ho funzionato. Lasciatemi spiegare come funziona questa rimozione, mantenendo i widget.

Un widget è noto dal layout principale.E lo rimuovi attraverso il layout. Facendo:

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

Se si utilizza takeAt (index) in un QLayout (o E'bambini), ti dà una QLayoutItem. Per accedere al widget all'interno, basta usare widget(). Ma non c'è modo di rimuovere il widget senza eliminarlo. Quindi questo approccio non è valido.

nella documentazione si racconta un modo per eliminare gli elementi:

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

una cosa speciale da notare in Qt è la seguente: Se si dispone di un albero hyerarchy di layout, ha aggiunto con addLayout () all'interno dei layout, non importa quanto profondo sia inserito il widget, è possibile rimuoverlo dai layout figlio o dai layout principali, se il percorso dell'albero dal layout e questo elemento è stato creato da layout figlio.

La cosa più semplice è tenere un elenco di puntatori a tutti gli elementi, in una tabella personalizzata. Quando si sgombra il tavolo di ricostruirlo, basta fare questo all'interno tuo 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. 

e funziona perfettamente, aggiorna il layout troppo da solo. Se vuoi mantenere gli elementi, salta semplicemente "elimina oggetto"; e usarli in seguito.

Una cosa importante da notare è che le funzioni di "rimozione" diverse funzionano in modo diverso (come ho capito su Qt Docs) in QList o widget simili e in un QLayout. In QList, removeAt rimuove effettivamente l'oggetto.

(Qt 4.7 QList Documenti) "rimuove la voce nella posizione di indice i. I deve essere una posizione di indice valido per la lista (cioè 0 < = i < dimensioni())".

In un QLayout, removeWidget o removeItem non rimuovono l'oggetto/widget, si ha la responsabilità di eliminarlo, come ho fatto prima.

(Qt 4.7 QLayout Documenti) "Rimuove il widget di widget dal layout. Dopo questa chiamata, è responsabilità del chiamante per dare il widget di una geometria ragionevole o al mettere il widget di nuovo in un layout."

Spero che sia d'aiuto. Se vedi qualche errore, potresti dirmi e modifico la risposta !.

Più sull'eliminazione qui: Other stackoverflow post

+0

layout() -> removeAt (widget); esiste SOLO per QGraphicsLayout. Quello che intendi è probabilmente layout() -> removeWidget (widget); – Bim

+0

Questo è anche ciò che puoi fare per rimuovere un widget da un layout SENZA cancellarlo.Se non si dispone del puntatore del widget, effettuare le seguenti operazioni: QLayoutItem * item = layout-> itemAt (0); QWidget * widget = oggetto-> widget(); if (widget! = NULL) { layout-> removeWidget (widget); // se si desidera eliminare il widget, fare: widget -> setParent (NULL); elimina widget; (la formattazione non funziona, ma si ottiene l'idea ...) – Bim

+0

FYI: Questo non è valido in Python poiché si deve occuparsi anche dell'oggetto C++ interno. – darkgaze

6

Un widget in Qt è un normale oggetto C++ e possono essere cancellati con l'operatore C++ delete come qualsiasi altro oggetto:

delete myWidget; 

In Qt c'è sempre una relazione padre-figlio tra i widget. Quando il widget genitore viene distrutto, elimina tutti i suoi figli. Di solito, non è necessario pensare di eliminare esplicitamente tutti i widget, ma i widget di livello superiore, cioè finestre e finestre di dialogo. Qt si occuperà dell'eliminazione di qualsiasi widget figlio.

QList::removeAt(int) non elimina l'oggetto rimosso, rimuove solo l'oggetto dall'elenco. Se anche voi volete eliminare l'oggetto che avrebbe dovuto fare qualcosa di simile:

delete myList.takeAt(0); 

Ciò si applica a tutte le funzioni, come removeAt(int), takeAt(int), takeFirst(), etc. Non hanno mai eliminare gli oggetti, li rimuovono solo dal contenitore (lista, layout, scrollarea, ecc.). Nella maggior parte dei casi la proprietà del widget viene quindi trasferita al chiamante, (il chiamante diventa responsabile dell'eliminazione del widget quando si interrompe la relazione genitore-figlio), ma non dare per scontato che sia sempre così, leggere sempre la documentazione della funzione .

+0

Grazie! Ma per quanto riguarda il mio particolare problema: ho un QBoxLayout. Faccio: takeAt (int) per prendere un elemento. Non è un widget, ma un oggetto QLayout. Per prendere il widget che uso. widget (vuoto). Ma il widget rimane all'interno. Come posso rimuovere il widget ed eliminare quel LayoutItem? Non c'è alcuna funzione per questo! – darkgaze

+0

FYI Questo non è valido in Python. Devi curare anche l'oggetto C++ interno. – darkgaze