Domanda

Sto usando il QWidget(QWidget *parent) costruttore. Questo genitore widget di contiene un sacco di widget figlio. Ho bisogno di cancellare tutti i widget il bambino dal genitore in fase di esecuzione. Come posso fare questo?

È stato utile?

Soluzione

È possibile utilizzare la seguente nel tuo widget genitore classe:

QList<QWidget *> widgets = findChildren<QWidget *>();
foreach(QWidget * widget, widgets)
{
    delete widget;
}

Altri suggerimenti

Risposta precedente è sbagliato !! Non è possibile utilizzare findChildren per eliminare i bambini di un widget, perchè findChildren di Qt4 in modo ricorsivo elenchi bambini. Pertanto, sarà eliminare figli dei figli, che poi possono essere eliminati due volte, potenzialmente crash l'applicazione.

Più in generale, in Qt, prendendo una lista di puntatori QObject e cancellare uno per uno è pericoloso, come la distruzione di un oggetto possono catena distruggere altri oggetti, grazie al meccanismo di titolarità genitore, oppure collegando un segnale destroyed() ad un fessura deleteLater(). Pertanto, distruggendo i primi oggetti nella lista può invalidare i prossimi.

È necessario Lista bambini widget mediante:

  • Passando la bandiera Qt :: FindDirectChildrenOnly a findChild se si utilizza QT5 (che non esisteva quando la domanda è stata posta ...)
  • Utilizzo delle funzioni QLayout della messa in vendita oggetti,
  • Uso QObject :: i bambini, e per ogni test se si tratta di un widget utilizzando isWidgetType () o un cast
  • Uso findChild () in un ciclo e cancellare il risultato fino a quando non restituisce un puntatore nullo

Per prendersi cura del problema ricorsività sottolineato da @galinette si può semplicemente rimuovere i widget in un ciclo while

while ( QWidget* w = findChild<QWidget*>() )
    delete w;

Riassumendo e integra:

Per QT5 in una riga:

qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));

Per QT5 per un sacco di bambini, Usare setUpdatesEnabled ():

parentWidget->setUpdatesEnabled(false);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
parentWidget->setUpdatesEnabled(true);

Si noti che questo non è sicuro eccezione! Mentre Qt non in questo momento sembrano generare eccezioni qui, il segnale distrutta () potrebbe essere collegato al codice che fa un tiro, o un oggetto sovrascritto :: childEvent (QChildEvent *) potrebbe gettare.

Una migliore sarebbe quella di utilizzare una classe di supporto:

class UpdatesEnabledHelper
{
    QWidget* m_parentWidget;
public:
    UpdatesEnabledHelper(QWidget* parentWidget) : m_parentWidget(parentWidget) { parentWidget->setUpdatesEnabled(false); }
    ~UpdatesEnabledHelper() { m_parentWidget->setUpdatesEnabled(true); }
};

...

UpdatesEnabledHelper helper(parentWidget);
qDeleteAll(parentWidget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));

Per Qt4:

QList<QWidget*> childWidgets = parentWidget->findChildren<QWidget*>();
foreach(QWidget* widget, childWidgets)
    if (widget->parentWidget() == parentWidget)
        delete widget;

La rimozione dal QLayout funziona sia in Qt4 e QT5:

QLayoutItem* child;
while (NULL != (child = layout->takeAt(0))) // or nullptr instead of NULL
    delete child;

QObject (e quindi QWidgets) rimuovere se stessi (automagicamente) dal loro genitore nella loro (QObject) distruttore.

Da Qt docs

Il seguente frammento di codice mostra un modo sicuro per rimuovere tutti gli elementi da un layout:

QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
    ...
    delete child;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top