2013-07-23 318 views
1

我創建了一個公共QGraphicsItem Node類,它爲與我的應用程序相關的一組屬性提供了getter/setter方法。該應用程序是用戶設計模型的圖編輯器。這個Node類用於填充也是公共QGraphicsScene Diagram類。Qt - 使用自定義QGraphicsItems保存自定義QGraphicsScene

我現在試圖在應用中實現一個加載/保存機制,使用戶能夠保存和重用模型 - 按照他們保存時的編輯方式進行編輯。我在計算如何解決這個問題時遇到了一些麻煩。

我已經知道我必須獲取QGraphicsItem對象的相關屬性並將它們保存到文件,然後在加載時使用我保存的數據重建場景。我的問題是:當我使用QGraphicsScene::items()函數時,它返回一個QList<QGraphicsItem *>。我能做些什麼來讓它返回QList<Node *>

如果我得到了我追加到場景中的所有節點的列表,我知道接下來要做什麼。

我開始意識到我可能不得不在我的Diagram類中重新實現items()函數,但我希望能更輕鬆地擺脫它。在這種情況下,有人可以解釋怎麼做嗎?

回答

1

我建議實施QGraphicsItem::type()方法,並使用qgraphicsitem_cast投入到所需的類。在你的情況下,你可以從一個公共的基類繼承所有你自定義的GraphicsItem。

你的基類是這樣的:

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

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

您的節點和你的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 
    } 
} 
+0

我忘了提及我也有一個公共的QGraphicsItem'Link'類。 'items()'方法也會返回這些實例。如果該項目是'Node'類,那麼如何將代碼調整爲_test_?我不希望/不需要處理'Link'對象... – Joum

+1

您可以通過爲所有項目使用通用基類並從中繼承您的'Node'和''Link'類來解決此問題。稍後,您可以使用'qgraphicsitem_cast'將其轉換爲該基類。我已經更新了代碼來證明這一點。 – tomvodi

+0

如果我沒有弄錯,從我在網上找到的,我的問題的_test_部分只是測試'if(graphicsItem!= 0)'。只有在轉換後,'graphicsItem'不是'MyGraphicsItem'類型,對嗎? – Joum

1

儘管項目func並返回一個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列表並將它們匹配到場景中的節點指針。

該體系結構還允許您在每個節點對象中包含一個鏈接節點ID列表,而不是使用Qt的父/子系統,在節點圖的情況下,它並不總是需要的。總體而言,我已經將這種體系結構用於許多QGraphicsScene應用程序,並且對於與其他項目具有複雜鏈接的項目而言,它確實使開發變得非常容易。

+0

謝謝,這似乎很有趣!雖然我認爲@thomas_b的做法似乎更簡單。我意識到索引對象類型的好處,但對於我所需要的可能太多了。 +1雖然:) – Joum

+1

沒問題,我只是認爲我把它放在那裏作爲參考,也許其他人將在未來受益。 – TheDarkKnight