Qt - 使用自定义QGraphicsItems保存自定义QGraphicsScene

时间:2013-07-23 08:51:56

标签: qt file-io save qgraphicsscene

我创建了一个公共QGraphicsItem Node类,它具有与我的应用程序相关的一堆属性的getter / setter方法。该应用程序是一个图表编辑器,用户可以在其中设计模型。此Node类用于填充公共QGraphicsScene Diagram类。

我现在正在尝试在应用程序中实现加载/保存机制,使用户能够保存和重用模型 - 按照保存时的方式对其进行编辑。我在弄清楚如何解决这个问题时遇到了一些麻烦。

我已经知道我必须获取QGraphicsItem对象的相关属性并将它们保存到文件中,然后在加载时,使用我保存的数据重建场景。我的问题是:当我使用QGraphicsScene::items()函数时,它会返回QList<QGraphicsItem *>。如果让它返回QList<Node *>我该怎么办?

如果我得到一个我附加到场景中的所有节点的列表,我知道下一步该做什么。

我开始意识到我可能不得不重新实现items()课程中的Diagram功能,但我希望我能更容易地逃脱它。在这种情况下,有人可以解释一下如何做到这一点吗?

2 个答案:

答案 0 :(得分:1)

我建议实施QGraphicsItem::type()方法并使用qgraphicsitem_cast投射到所需的类中。在您的情况下,您可以从公共基类继承所有自定义GraphicsItem。

你的基类看起来像这样:

class MyGraphicsItem: public QGraphicsItem
{
    enum { Type = UserType + 1 };

    int type() const { return Type; }
};

您的Node和您的Link类将继承此基础:

class Node : public MyGraphicsItem
{
    // ... 
};

class Link : public MyGraphicsItem
{
    // ... 
};

在其他地方,您可以将QGraphicsItem强制转换为基类MyGraphicsItem,例如:

QList<QGraphicsItem*> allItems = graphicsScene->items();
foreach (QGraphicsItem *item, allItems) {
    // Using qgraphicsitem_cast 
    MyGraphicsItem* graphicsItem = qgraphicsitem_cast<MyGraphicsItem*>(item);
    if (graphicsItem) {
        // Do something with MyGraphicsItem
    }
}

答案 1 :(得分:1)

虽然items函数返回QGraphicsItem指针的列表,但您可以尝试使用dynamic_casting来检查它是否是Node指针,或者使用Qt元数据和type()函数。

然而,我经常使用的方法,也可以在其他方面帮助你,是为每种类型的对象和项目ID的静态列表维护一个唯一的id。例如: -

class BaseItem : public QGraphicsItem
{
    public:
        BaseItem(QGraphicsItem* parent)
          : QGraphicsItem(parent), m_Id(m_NextId++) // initialising the object's unique Id
        {
        }

        unsigned int ID() const
        {
            return m_Id;
        }

    private:
        static unsigned int m_NextId; // the next Object Id, initialised to 0 in implementation
        unsigned int m_Id; // the object's unique Id

}

class Node : public BaseItem
{
    public:
        Node(QGrahicsItem* parent)
          : BaseItem(parent)
        {
            m_NodesList.push_back(m_Id);
        }

    private:
        static QList<unsigned int> m_sNodesList; // all Node ids in the scene

        QList<unsigned int> m_linkedNodeList; // linked nodes
}

添加到GraphicsScene的所有项目都继承自BaseItem

你还有一个Node Ids的静态列表,所以你可以迭代遍历所有这些以进行加载/保存,你可以在基类中添加一个静态帮助函数来返回一个节点列表,通过搜索列表节点ID并将它们与场景中的节点指针相匹配。

此体系结构还允许您在每个Node对象中包含链接节点ID的列表,而不是使用Qt的父/子系统,在节点图的情况下,并不总是需要。< / p>

总的来说,我已经将这个架构用于许多QGraphicsScene应用程序,并且它确实使得开发非常容易用于与其他项目有复杂链接的项目。