QList mit QVariant

Alles rund um die Programmierung mit Qt
Antworten
TheBert
Beiträge: 21
Registriert: 1. September 2009 14:27

QList mit QVariant

Beitrag von TheBert »

Hi,

ich hab die doku zu QVariant rauf und runter gelesen, aber nirgendst etwas gelesen, ob man in QVariant auch einen zeiger speichern kann? Wenn dem doch so ist, habe ich es vermutlich überlesen.

Ich habe eine QList<QVariant> und möchte darin die zeiger verschiedener objekte speichern (QTextEdit, QPushButton, etc.), geht das?

Und dann wäre da noch der destructor, ich habe jetzt die liste mit den objekten, wie lösche ich die zeiger in der liste?

Eigentlich wollte ich mit qDeleteAll(anfang, ende) alles löschen, doch das geht ja mit QVariant nicht.

Ich iteriere also durch die liste, muss ich da jetzt jedes objekt casten und dann löschen?

Oder reicht es gar, wenn ich nur die liste leere mit .clear()? Vermutlich aber nicht.

Danke!

TestKlasse.h

Code: Alles auswählen

class TestKlasse
{
...

private:
QList<QVariant> myItems;
QPushButton *myButton;
QTestEdit *myTextEdit;
}
TestKlasse.cpp

Code: Alles auswählen


TestKlasse::TestKlasse()
{
myButton = new QPushButton();

myItem.append(myButton);
}

TestKlasse::~TestKlasse()
{
    QList<QVariant>::iterator it;

    for(it=myItems.begin();it!=myItems.end();++it)
    {
        //hier hängts
    }

myItems.clear();
}

[/code]
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

Warum nimmst du nicht einfach eine QList<QObject*> aka QObjectList oder QList<QWidget*> ... und wozu das eingentlich?

Wenn du brav immer deine Objecte in irgendein parent addest löscht dieses Parent seine childs wenns selbst zerstört werden soll ... daher macht man doch

Code: Alles auswählen

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])         
{
 QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
  
} // hier wird w dann zerstört und räumt alles auf was sein child ist ...
siehe http://doc.qt.nokia.com/4.6/qobject.html#details
Detailed Description

The QObject class is the base class of all Qt objects.

QObject is the heart of the Qt object model. The central feature in this model is a very powerful mechanism for seamless object communication called signals and slots. You can connect a signal to a slot with connect() and destroy the connection with disconnect(). To avoid never ending notification loops you can temporarily block signals with blockSignals(). The protected functions connectNotify() and disconnectNotify() make it possible to track connections.

QObjects organize themselves in object trees. When you create a QObject with another object as parent, the object will automatically add itself to the parent's children() list. The parent takes ownership of the object; i.e., it will automatically delete its children in its destructor.
In Qt werden laufen Objecte re-parent()ed ... zB wenn sie in nem Layout stekcen und du das Layout per QWidget::setLayout() einem Widget zuweist dann bekommen alle ge-layouteten Sachen dieses Widget als Parent ... es fehlt also nicht an QList<QVariant> sondern Basis API ;)
Zuletzt geändert von padreigh am 5. Oktober 2010 22:32, insgesamt 1-mal geändert.
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
TheBert
Beiträge: 21
Registriert: 1. September 2009 14:27

Beitrag von TheBert »

Danke für die antwort!

Wenn alle objekte die in die liste kommen von QWidget oder QObject abgeleitet sind wäre das ok, aber mir gehts eher um die theorie, wenn z.b. ein objekt nicht von den o.g. abgeleitet ist, verwende ich QVariant.

Wie gehe ich da vor beim hinzufügen der zeiger und beim löschen im destructor?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Dann musst du eben casten wie Du schon geschrieben hast. Aber was nützt es Dir? delete auf void* ist nicht möglich also musst du wieder auf einen korrekten Datentyp casten - nur welchen?
Und warum dann nicht gleich QList<void*> benutzen? Löschen geht dann natürlich genausowenig.
Was sollte man auch in einer Liste speichern was nicht einmal eine gemeinsame Basisklasse hat? Die Idee ist also grundsätzlich falsch.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
TheBert
Beiträge: 21
Registriert: 1. September 2009 14:27

Beitrag von TheBert »

Christian81 hat geschrieben:Was sollte man auch in einer Liste speichern was nicht einmal eine gemeinsame Basisklasse hat? Die Idee ist also grundsätzlich falsch.
Danke für den hinweis, dann werde ich alle objekte in der liste von QObject ableiten und die liste als QList<QObject*> deklarieren. Das wäre dann der bessere ansatz?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

TheBert hat geschrieben:Das wäre dann der bessere ansatz?
Keine Ahnung... Besser als QVariantList allemal.
Brauchst du denn jetzt wirklich alles mögliche an Objekten in einer Liste? Wie willst du dann darauf zugreifen? Nur dass alle Objekte in einer Liste stehen diesen Ansatz wählen ist nicht gut... Auf was für ein Interface willst du dich stützen? Für alles was über das Interface der Basisklasse (von mir aus QObject) hinaus geht, musst du den konkreten Type wissen und casten, dann stehen dir die Methoden zur Verfügung. Das bedeutet, du musst wie wild rumcasten, oder irgendwo zusätzlich Typinformationen speichern, mit denen du dann casten kannst. Über lange switch-Konstrukte musst du dann trotzdem gehen.

Kurz: Überlg dir ein besseres Programmdesign. Zum mal damit spielen ist das OK, für produktiven Einsatz ist es zu fehleranfällig und inperformant.
TheBert
Beiträge: 21
Registriert: 1. September 2009 14:27

Beitrag von TheBert »

Ich hab mich jetzt weiter eingelesen und und bin zu testzwecken gleich von QObject zu QGraphicsItem gegangen, und habe folgendes erstellt, jedoch wird in der methode deserialize() das auslesen beim kompilieren mit einem fehler abgebrochen.

Ich habe das listing aus einem qt buch, darin wird das auch so gemacht, bis auf das, das ich ein QGraphicsItem auslesen möchte.

Bitte um hilfe, wo der fehler ist, danke!

Code: Alles auswählen

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    QList<QGraphicsItem*> items;

    QGraphicsTextItem *tItem;
    QGraphicsLineItem *lItem;
    QGraphicsRectItem *rItem;
    QGraphicsItem *gItem;

    void serialize();
    void deserialize();
};

Code: Alles auswählen

[...]
void MainWindow::init()
{
    tItem = new QGraphicsTextItem("Test");
    tItem->setData(0, "TextItem");
    lItem = new QGraphicsLineItem(10,5,10,20);
    lItem->setData(0, "LineItem");
    rItem = new QGraphicsRectItem(0,0,100,100);
    rItem->setData(0, "RectItem");

    items.append(tItem);
    items.append(lItem);
    items.append(rItem);
}

void MainWindow::serialize()
{
    QFile File("/home/bert/file.dat");
    File.open(QIODevice::WriteOnly);
    QDataStream ds(&File);
    ds << items;
    File.close();

    qDeleteAll(items.begin(), items.end());
    items.clear();
}

void MainWindow::deserialize()
{
    QFile File("/home/bert/file.dat");
    File.open(QIODevice::ReadOnly);
    QDataStream ds(&File);
    
    while(!ds.atEnd())
    {
        ds >> gItem;
        items.append(gItem);
    }

    File.close();

    if(items.count() > 0)
    {
        QList<QGraphicsItem*>::iterator it;

        for(it=items.begin();it!=items.end();++it)
        {
            QGraphicsItem *itm = qgraphicsitem_cast<QGraphicsItem*>(*it);
            qDebug(qPrintable(itm->data(0).toString()));
        }
    }
}
Fehlermeldung:
error: no match for ‘operator>>’ in ‘ds >> ((MainWindow*)this)->MainWindow::gItem’
Was im eigentlich erreichen will ist folgendes, ich möchte gerne meine QList<QGraphicsItem*> in eine datei serialisieren, wieder auslesen und wieder eine QList<QGraphicsItem*> erhalten.
Zuletzt geändert von TheBert am 6. Oktober 2010 23:01, insgesamt 3-mal geändert.
kater
Beiträge: 306
Registriert: 29. Dezember 2009 01:13
Wohnort: Darmstadt

Beitrag von kater »

Und wo ist die Fehlermeldung?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Du schreibst eine QList<QGraphicsItem*> in den Datastream aber beim rauslesen versuchst Du ein QGraphicsItem* zu lesen. Wie soll das gehen?
Des weiteren speicherst Du Pointer und leist sie später wieder aus- was soll das? Woher willst Du wissen das die Pointer noch gültig sind? Nach einem Neustart können sie gar nicht mehr gültig sein!
Und nun zur Fehlermeldung - QDataStream hat nunmal keinen operator >>(void*) bzw. operator>>(QGraphicsItem*) und zwar aus den oben genannten Grund.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten