序列化QGraphicsScene内容

Rob*_*Rob 8 c++ qt

我使用Qt QGraphicsScene类,添加预先定义的项目,如QGraphicsRectItem,QGraphicsLineItem等我想现场的内容序列化到磁盘.但是,基QGraphicsItem类(我使用的其他项派生自)不支持序列化,所以我需要滚动自己的代码.问题是所有对这些对象的访问都是通过基QGraphicsItem指针进行的,所以我的序列化代码很糟糕:

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
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

这不是好的代码恕我直言.所以,我可以像这样创建一个ABC类:

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
  }
  ...
};
Run Code Online (Sandbox Code Playgroud)

然后我可以使用添加Rect对象 QGraphicsScene::addItem(new Rect(,,,));

但这并没有真正帮助我,因为以下将崩溃:

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

我能以任何方式使这项工作?

Chr*_*ier 3

我同意其他海报的观点,QGraphicsItem确实可以被视为一个视图项,因此将模型数据分离到它自己的类中可能会更好。

也就是说,我认为你的崩溃是由于演员阵容不当造成的。

如果您执行以下操作:

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);
Run Code Online (Sandbox Code Playgroud)

您应该看到 r == qi,r == qr,但是 r != i。如果您考虑如何在内存中表示多重继承的对象,则第一个基类在内存中第一个,第二个基类在第二个,依此类推。因此,指向第二个基类的指针将偏移第一个基类的大小[大约]。

因此,要修复您的代码,我认为您需要执行以下操作:

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(...);
}
Run Code Online (Sandbox Code Playgroud)

这是众多原因之一,我喜欢尽可能避免多重继承。我强烈建议按照之前的建议分离模型数据。