Clearing von Layouts in Qt
Bin ich erstellen, eine Anwendung in Qt, die es Benutzern ermöglicht zu schleppen, um verschiedene "Module" in ein QGraphicsView. Wenn eines dieser Module ausgewählt ist, sendet er ein signal um, welches dann abgeholt von einem "ConfigurationWidget", die eine Seite-panel, welches anzeigen soll, können alle relevanten Parameter des ausgewählten Moduls:
class ConfigurationWidget : public QWidget
{
Q_OBJECT
public:
ConfigurationWidget(QWidget *parent) : QWidget(parent) {}
public slots:
void moduleSelected(Module* m)
{
if(layout())
{
while (itsLayout->count()>0)
{
delete itsLayout->takeAt(0);
}
}
delete layout();
itsLayout = new QFormLayout(this);
itsLayout->addRow(QString(tr("Type:")), new QLabel(m->name()));
itsLayout->addRow(QString(tr("Instance:")), new QLabel(m->instanceID()));
//... Display a whole bunch of other fields that depends on the module
}
};
Das problem ist, dass die ConfigurationWidget nie wird tatsächlich gelöscht, wenn ein Modul ausgewählt ist. Die neuen Felder sind nur gezeichnet, über die alten. Ich habe versucht, verschiedene Kombinationen von hide() und show(), invalidate(), update(), etc. ohne Erfolg.
Was ist der richtige Weg, um ein widget, das können Sie ändern Sie die Felder wie dieses on-the-fly?
InformationsquelleAutor rcv | 2011-01-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den code der Schleife, die ich verwendet habe, vor, ist wie folgt:
Hoffentlich wird hilfreich sein für Sie!
if(QSpacerItem *SpacerItem = Item->spacerItem()){ delete SpacerItem; }
als gut 🙂Weitere Untersuchungen zeigen auch, dass
delete item
ist unnötig, da die Qt-Griffe, die für uns (verwenden SieQlayout::count()
zu überprüfen)Sie brauchen nicht die
if (item->widget())
. LöschenNULL
ist ein nop.das führt zu einem Fehler:
item->spacerItem()
im wesentlichenreturn dynamic_cast<QSpacerItem*>(item)
. I. e. Sie würde das doppelte Befreiung, block im Speicher. Hinweis: ich kenne diese nur empirisch.Dies ist die einzige gültige code von allen die Antworten. Es gibt jedoch eine effizientere Methode, die nicht erforderlich ist die Rekursion. Zuerst löschen Sie alle widgets, die direkte Kinder, dann löschen Sie layout-Elemente, ohne die Rekursion.
InformationsquelleAutor Wes Hardaker
Wenn Sie übertragen Sie das layout zu einem anderen widget auf dem Stapel reserviert, die widgets in diesem layout werden die Kinder der neuen widget. Wenn das temporäre Objekt außerhalb des Gültigkeitsbereichs zerstört es automatisch das layout und alle widgets.
QLayout::clear()
...InformationsquelleAutor alexisdm
Sieht es aus wie der beste Weg, dies zu tun, ist die Verwendung einer QStackedLayout, wie angedeutet durch armonge:
Behoben.
InformationsquelleAutor rcv
Ich vor kurzem laufen in das gleiche problem mit einem QFormLayout.
Was für mich gearbeitet (und ist auch in der Qt-Dokumentation: http://qt-project.org/doc/qt-5/layout.html) war die takeAt(int) - Methode.
InformationsquelleAutor Kádi
Mit
while((item = layout->takeAt(0)))
verursachen Warnmeldung "Invalid index nehmen Sie bei 0".Ich benutze
count()
stattKommt drauf an, aber ja, im Allgemeinen Fall ist es nicht klug, rufen Sie löschen auf nulltpr. stackoverflow.com/questions/6731331/...
Anstelle von "löschen widget', ich würde vorschlagen, mit widget->deleteLater(). In den meisten Fällen, es wäre schwer, den Unterschied bemerken, aber es kann einer werden. Als Dokumentation über QObject sagt: "Das Objekt wird gelöscht, wenn die Kontrolle wieder an die event loop". Dies ist der wichtigste Punkt. Ist es möglich das widget sendet irgendein signal, und nach dem senden das signal einige andere Anrufe in das gleiche widget-Instanz. Wenn Sie löschen würde-widget in einem "raw-Weg", dann würden Sie nicht mehr gültig sind, und in diesem Fall kann man nicht behandeln, alles nach dem signal gesendet wird.
InformationsquelleAutor Dorian
Reparent die Elemente auf NULL, wenn Sie wollen, dass Sie verschwindet vom Fenster. Ich hatte ähnliche Probleme vor kurzem und übernahme gelöst.
InformationsquelleAutor nyu