VLayout Widget anhand des Index löschen?

Alles rund um die Programmierung mit Qt
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

VLayout Widget anhand des Index löschen?

Beitrag von gast23 »

Hallo,

wie lösche ich ein Widget aus dem Layout nur mit Hilfe des Index?

_Hab schon in der Doku geschaut und finde keine Möglichkeit...

TakeAt funktioniert nicht...

Viele Grüße
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Qt-Doku hat geschrieben: To remove a widget from a layout, call removeWidget(). Calling QWidget::hide() on a widget also effectively removes the widget from the layout until QWidget::show() is called.
Da man eher einen Pointer auf ein Widget hat (man will es ja befüllen etc.) als einen Index zu irgendeinen Layout ist das die korrekte Vorgehensweise.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

Normalerweise werden Widgets auf dem BoxLayout anhand einer Referenz gelöscht. Sprich du machst dir eine: "QList <QBeliebigesWidget*> ListName;" oder du benutzt den/die Pointer auf das Objekt selbst und rufst dazu "removeWidget(QWidget* name);" auf.

Für die Liste initialisierst du die Widgets dort trägst sie dann in das BoxLayout ein.
Dann kannst du anhand der Listennummer ".at(0)" das Widget aus dem BoxLayout mit "removeWidget(QWidget*)" bzw. mit "removeWidget( ListName.at(0) )" entfernen.

BoxLayout erzeugen zur Laufzeit:

Code: Alles auswählen

    QVBoxLayout* myLayer = new QVBoxLayout(this);
    QPushButton* firstBtn = new QPushButton("first",this);
    QPushButton* secondBtn = new QPushButton("second",this);
    QPushButton* thirdBtn = new QPushButton("third",this);
    this->setLayout(myLayer);
    myLayer->addWidget(firstBtn);
    myLayer->addWidget(secondBtn);
    myLayer->addWidget(thirdBtn);
Solltest du nun diesen Code erweitern um die Zeile:

Code: Alles auswählen

myLayer->removeWidget(firstBtn);
Siehst du, dass der 1. Button nicht mehr in dem Layout ist.

Wenn du es nun noch löschen möchtest erweiterst du um:

Code: Alles auswählen

delete(firstBtn);
Oder änderst den Status:

Code: Alles auswählen

firstBtn->setVisible(false);
//bzw.
firstBtn->hide();
Das ganze wendest du einfach auf die QList an und alles läuft zu deiner Zufriedenheit.
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag von gast23 »

Ok QList war auch meine Überlegung...

Danke.

Trotz der Speicherproblematik in C++ finde ich das sehr schlecht das ein "modernes" UI Framework für die Layoutcontainer keine Methode Widget* remove(int) bereitstellt...
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

Es gibt doch eine Möglichkeit:

Code: Alles auswählen

myLayer->removeItem(myLayer->takeAt(0));
Bezogen auf mein Post (Hauptteil+dieser Code hier), entfernt es den ersten Button aus dem BoxLayout.

PS: Grundsätzlich geht man aber davon aus, das man die Refenrenz benutzt, denn diese Methode (s.o.) würde teilweise implizieren, das der Programmierer nicht umbedingt eine Referenz für das Objekt besitzt und weiterhin ist es Problematisch. Wenn zum Beispiel ein anderes Widget dieses überlagert könnte es nach dem entfernen aus dem BoxLayout als Leiche im Programm herumdümpeln. Wollte ich nur mal so anmerken. ;)
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag von gast23 »

Also bei mir funktioniert das leider nicht...

Code: Alles auswählen

    while(layout->count() > 2) {

        QLayoutItem* l = layout->takeAt(2);
        layout->removeItem(l);
        delete l;

    }
Das Layout wird zwar geleert aber das Widget bleibt trotzdem erhalten. (In deinem Beispiel der Button, in meinem Programm ein anderes Widget)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Auch wenn ich immer noch nicht kapiere warum man ein QWidget über den Layoutindex löschen sollte... http://doc.trolltech.com/4.7/qlayoutitem.html#widget
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag von gast23 »

Ich gebe zu im C++ Umfeld ist das nicht speichern eines Zeigers schon unsicher... aber im Kontext des Prototypings wo man schnelle Ergebnisse braucht wäre diese Methode sehr hilfreich.
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

Geht alles: Mein Code mit deinem in ""richtiger"" Form erweitert ..

Code: Alles auswählen

    QVBoxLayout* myLayer = new QVBoxLayout(this);
    QPushButton* firstBtn = new QPushButton("first",this);
    QPushButton* secondBtn = new QPushButton("second",this);
    QPushButton* thirdBtn = new QPushButton("third",this);

    this->setLayout(myLayer);

    myLayer->addWidget(firstBtn);
    myLayer->addWidget(secondBtn);
    myLayer->addWidget(thirdBtn);
    
    if(myLayer->count() > 2) {
        QLayoutItem* cItem = myLayer->itemAt(2);
        myLayer->removeItem(cItem);
        QPushButton* cacheBtn = dynamic_cast<QPushButton*>(cItem->widget());
        delete(cacheBtn);
        delete(cItem);
    }
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag von gast23 »

Ja delete widget() geht natürlich... aber musste nun doch die Liste nehmen da ich noch einige andere Operationen ausführen musste und ich keine Lust hab ständig zu casten :/

In anderen Frameworks könnte man so etwas schreiben...

Code: Alles auswählen

                while (layout.Children.Count > 2)
                    layout.Children.RemoveAt(2);
Ich würde es nett finden wenn Qt folgendes könnte:

Code: Alles auswählen

                while (layout->Children.Count() > 2)
                   delete layout->Children.RemoveAt(2);
Zuletzt geändert von gast23 am 24. Oktober 2010 14:44, insgesamt 1-mal geändert.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

In Qt reagieren die Besitzer von QWidgets (Layouts, Tabellen, usw) auf das "destroyed()"-Signal. D.h. ersetze doch einfach:

Code: Alles auswählen

  if(myLayer->count() > 2) {
        QLayoutItem* cItem = myLayer->itemAt(2);
        myLayer->removeItem(cItem);
        QPushButton* cacheBtn = dynamic_cast<QPushButton*>(cItem->widget());
        delete(cacheBtn);
        delete(cItem);
    }
durch

Code: Alles auswählen

thirdBtn->deleteLater();
und fertig...
gast23 hat geschrieben:Ich gebe zu im C++ Umfeld ist das nicht speichern eines Zeigers schon unsicher... aber im Kontext des Prototypings wo man schnelle Ergebnisse braucht wäre diese Methode sehr hilfreich.
Gerade im Prototyping macht es Sinn mit dem Designer zu arbeiten und einer der beiden "Inheritance Approaches" einzusetzen. Gerade in diesem Fall hast du also bereits die Pointer auf die Objekte und kannst z.B. mit

Code: Alles auswählen

ui.btnIrgendwas->deleteLater(); ui.btnIrgendwas=NULL;
das Widget aus dem Layout entfernen...

hth..
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag von gast23 »

Die Objekte sind dynamisch! Initial gibt es keine und durch bestimmte Nutzeraktionen werden die erst erzeugt.

Deswegen ja Index weil der ist praktisch immer bekannt ;)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Und gerade eben weil sie dynamisch sind - wie kann man dan wissen das an Position 42 das Widget ist welches ich löschen will? Und wie kann man dann die dynamisch erstellten Widgets korrekt befüllen und verändern wenn man keine Pointer oder eindeutige Objektnamen dazu hat etc.? Der Ansatz passt imho irgendwie nicht.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag von gast23 »

Naja es gibt schon Fälle...

Annahme: Alle Widgets liegen in dem Container und man kann über den Index einen Zeiger erhalten, dann kannst du doch alles damit tun...

Es geht nicht darum Widget XY zu löschen oder zu kennen sondern allgemein alle Widgets des Containers bzw. ab einem bestimmten Index zu löschen ;)
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

gast23 hat geschrieben:Die Objekte sind dynamisch!
Dann schreibst du beim Erstellen ja eh Code.. spielt doch keine Rolle ob "Klasse *i = new Klasse()" oder "klList << new Klasse()"...
gast23 hat geschrieben: Deswegen Index weil der ist praktisch immer bekannt ;)
Ist er das? Bei meinen Applikationen wissen die Objekte innerhalt eines Layouts nichts über das Layout.. ein "clicked()" Signal eines Buttons hat ebenso wenig Information über den Index wie ein "textChanged()" - Signal eines LineEdits..

[EDIT] Christian war schneller ;)
Antworten