2010-06-08 18 views
7

Estoy usando la clase Qt QGraphicsScene, agregando elementos predefinidos como QGraphicsRectItem, QGraphicsLineItem, etc. y deseo serializar el contenido de la escena en el disco. Sin embargo, la clase base QGraphicsItem (de la que derivan los otros elementos que utilizo) no es compatible con la serialización, por lo que necesito transferir mi propio código. El problema es que todo el acceso a estos objetos es a través de un puntero QGraphicsItem base, por lo que el código de serialización que tengo es horrible:Serialización QGraphicsScene contents

QGraphicsScene* scene = new QGraphicsScene; 
scene->addRect(QRectF(0, 0, 100, 100)); 
scene->addLine(QLineF(0, 0, 100, 100)); 
... 
QList<QGraphicsItem*> list = scene->items(); 
foreach (QGraphicsItem* item, items) 
{ 
    if (item->type() == QGraphicsRectItem::Type) 
    { 
    QGraphicsRectItem* rect = qgraphicsitem_cast<QGraphicsRectItem*>(item); 
    // Access QGraphicsRectItem members here 
    } 
    else if (item->type() == QGraphicsLineItem::Type) 
    { 
    QGraphicsLineItem* line = qgraphicsitem_cast<QGraphicsLineItem*>(item); 
    // Access QGraphicsLineItem members here 
    } 
    ... 
} 

Esto no es bueno en mi humilde opinión código. Así, en lugar que podría crear una clase ABC como esto:

class Item 
{ 
public: 
    virtual void serialize(QDataStream& strm, int version) = 0; 
}; 

class Rect : public QGraphicsRectItem, public Item 
{ 
public: 
    void serialize(QDataStream& strm, int version) 
    { 
    // Serialize this object 
    } 
    ... 
}; 

puedo continuación, añadir objetos Rect usando QGraphicsScene::addItem(new Rect(,,,));

Pero esto realmente no me ayuda como el siguiente se colgará:

QList<QGraphicsItem*> list = scene->items(); 
foreach (QGraphicsItem* item, items) 
{ 
    Item* myitem = reinterpret_class<Item*>(item); 
    myitem->serialize(...) // FAIL 
} 

¿De alguna manera puedo hacer que esto funcione?

+0

¿Por qué 'myitem-> serialize()' falla.No lo estoy viendo? –

Respuesta

3

Estoy de acuerdo con los otros carteles , QGraphicsItem realmente podría verse como un elemento de vista y, por lo tanto, separar los datos de su modelo en su propia clase probablemente sería mejor.

Dicho esto, creo que su bloqueo se debe a un lanzamiento inapropiado.

Si hace lo siguiente:

Rect *r = new Rect(); 
QGraphicsItem *qi = reinterpret_cast<QGraphicsItem*>(r); 
QGraphicsRectItem *qr = reinterpret_cast<QGraphicsRectItem*>(r); 
Item *i = reinterpret_cast<Item*>(r); 
qDebug("r = %p, qi = %p, qr = %p, i = %p", r, qi, qr, i); 

debería ver que r == qi, r == qr, pero r = i!. Si piensas cómo se representa en la memoria un objeto que se hereda de forma múltiple, la primera clase base está primero en la memoria, la segunda clase base es la segunda, y así sucesivamente. Por lo tanto, el puntero a la segunda clase base estará compensado por [aproximadamente] el tamaño de la primera clase base.

Así que para fijar su código, creo que hay que hacer algo como:

QList<QGraphicsItem*> list = scene->items(); 
foreach (QGraphicsItem* item, items) 
{ 
    Rect* myrect = reinterpret_class<Rect*>(item); // needed to figure out the offset to the Item part 
    Item* myitem = reinterpret_class<Item*>(myrect); 
    myitem->serialize(...); 
} 

Ésta es una de las muchas razones, me gustaría evitar la herencia múltiple siempre que sea posible. Recomiendo separar los datos del modelo, como se recomendó anteriormente.

1

Serializar QGraphicsItem no es una buena idea. Se supone que un QGrahpicsScene representa sus datos. En lugar de serializar la representación, es mejor serializar los datos/modelo de su aplicación.

Si desea registrar la disposición de las entidades gráficas, tal vez puede usar un QGraphicsItem personalizado y dibujar en un QPicture.

+0

Los elementos contienen todo lo que necesito para serializar, por lo que se pueden considerar datos/modelo en este caso. – Rob

+0

Por cierto, no parece haber soporte para vincular un QGraphicsScene a un modelo separado. – Rob

0

Si realmente desea serializar estos elementos crean

QDataStream &operator<<(QDataStream &, const AppropriateSubclass&); 
QDataStream &operator>>(QDataStream &, AppropriateSubclass&); 

para cada una de las subclases QGraphicsItem que le gustaría para serializar, estas funciones son funciones que no son miembros. El enfoque también se explica en la documentación QDataStream

pero apoyo Stephens respuesta, es posible que desee considerar tirando de los datos reales de la escena y ponerlo en una clase de modelo separado

+0

Esto no funciona a menos que transfiera cada QGraphicsItems al tipo correcto antes de intentar transmitirlo. – Rob

Cuestiones relacionadas