1

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

我现在正在尝试在应用程序中实现加载/保存机制,使用户能够保存和重用模型 - 像保存时一样编辑它们。我在弄清楚如何解决这个问题时遇到了一些麻烦。

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

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

我开始意识到我可能不得不items()在我的课堂上重新实现这个函数Diagram,但我希望我能更轻松地摆脱它。在这种情况下,有人可以解释一下怎么做吗?

4

2 回答 2

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

您还有一个静态节点 ID 列表,因此您可以遍历所有这些以进行加载/保存,并且您可以在基类中添加一个静态帮助函数以返回节点列表,方法是搜索节点 ID 列表和将它们与场景中的节点指针相匹配。

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

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

于 2013-07-23T09:46:36.720 回答
1

我建议实现该QGraphicsItem::type()方法并使用qgraphicsitem_cast转换为所需的类。在您的情况下,您可以从一个公共基类继承所有自定义 GraphicsItems。

您的基类将如下所示:

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
    }
}
于 2013-07-23T09:24:55.813 回答