Qt QGraphicsScene繪圖節點保存及恢復


在上一篇文章中 Qt 遍歷不規則樹的節點,介紹了節點保存及恢復,但是恢復時不是將原有節點原樣恢復。這里介紹怎樣恢復原樣。

思路:要恢復恢復,首先肯定要有節點的坐標(在scene中)。節點恢復后,還要使用箭頭連接。據此,我們保存時,要保存節點坐標,及箭頭首尾節點。根據上一篇文章,我們在創建時已經給節點了唯一標識。

唯一標識代碼:

QString getGUID()
{
    QUuid id = QUuid::createUuid();
    QString strId = id.toString();
    return strId;
}

保存函數及說明如下:

bool OperateItemFile::SaveItemArrowFile(QList<DiagramItem *> &pItemList, QList<Arrow *> &pArrowList, QString itFilePath)
{
    if(pItemList.size() > 0){
        QDomDocument doc;
        doc.appendChild( doc.createProcessingInstruction("xml", XML_HEAD_INFO));
        QFile file(itFilePath);
        if (!file.open(QIODevice::WriteOnly)){
            return false;
        }
        QDomElement root = doc.createElement("Root");
        doc.appendChild(root);
        //設備節點
        QDomElement dev = doc.createElement("DeviceVerb");
        root.appendChild(dev);
        for(int i=0 ;i<pItemList.size() ;i++){
            QDomElement ItemE = doc.createElement("Device");
            ItemE.setAttribute("ItemId" ,pItemList.at(i)->getItemId());
            ItemE.setAttribute("left" ,pItemList.at(i)->boundingRect().left());
            ItemE.setAttribute("top" ,pItemList.at(i)->boundingRect().top());
            ItemE.setAttribute("right" ,pItemList.at(i)->boundingRect().right());
            ItemE.setAttribute("bottom" ,pItemList.at(i)->boundingRect().bottom());
            ItemE.setAttribute("name" ,pItemList.at(i)->getText());
            ItemE.setAttribute("x" ,pItemList.at(i)->pos().x());
            ItemE.setAttribute("y" ,pItemList.at(i)->pos().y());
            ItemE.setAttribute("z" ,pItemList.at(i)->zValue());
            ItemE.setAttribute("color" ,pItemList.at(i)->brush().color().rgb());
            ItemE.setAttribute("brushstyle" ,pItemList.at(i)->brush().style());
            ItemE.setAttribute("type" ,pItemList.at(i)->diagramType());
            getItemChild(pItemList, pItemList.at(i), doc, ItemE);
            dev.appendChild(ItemE);
        }

        //保存箭頭
        if(pArrowList.size() > 0){
            QDomElement arrow = doc.createElement("ArrowVerb");
            root.appendChild(arrow);
            for(int i=0 ;i<pArrowList.size() ;i++){
                QDomElement ArrowItem = doc.createElement("Arrow");
                ArrowItem.setAttribute("StartItemId" ,pArrowList.at(i)->getStartId());
                ArrowItem.setAttribute("EndItemId" ,pArrowList.at(i)->getEndId());
                arrow.appendChild(ArrowItem);
            }
        }

        QString xml = doc.toString();
        QTextStream txtOutput(&file);
        txtOutput.setCodec("UTF-8");
        txtOutput<<xml;
        file.close();
    }
    return true;
}

  函數中的參數依次是:所有節點,所有箭頭,及保存的文件名。

恢復函數如下:

bool OperateItemFile::getNormalItem(QString itemType, QList<DiagramItem *> *pList, QDomNodeList &domList, QMenu *itemMenu)
{ for (int i = 0; i < domList.size(); i++) { QStringList szAttrVal; QDomElement fileElem = domList.at(i).toElement(); QString l = fileElem.attribute("left"); QString t = fileElem.attribute("top"); QString r = fileElem.attribute("right"); QString b = fileElem.attribute("bottom"); QString name = fileElem.attribute("name"); QString id = fileElem.attribute("ItemId"); QString x = fileElem.attribute("x"); QString y = fileElem.attribute("y"); QString z = fileElem.attribute("z"); QString type = fileElem.attribute("type"); QString rgb = fileElem.attribute("color"); QString brushstyle = fileElem.attribute("brushstyle"); DiagramItem* pItem = new DiagramItem((DiagramItem::DiagramType)type.toUInt() ,itemMenu); pItem->setPos(QPointF(x.toFloat() ,y.toFloat())); pItem->setZValue(z.toFloat()); pItem->setBkColor(QColor(rgb.toUInt())); pItem->setItemId(id); pItem->setText(name); pItem->setBrush(QBrush(rgb.toUInt(), (Qt::BrushStyle)brushstyle.toUInt())); if(itemType.compare("Port") == 0) { QString parentItemId = fileElem.attribute("parentItemId"); pItem->setParentItemId(parentItemId); } szAttrVal.push_back(name); szAttrVal.push_back(rgb); szAttrVal.push_back("False"); szAttrVal.push_back(""); szAttrVal.push_back(""); szAttrVal.push_back(""); szAttrVal.push_back(""); for (int j = 0; j < szAttrName.size(); j++) { pItem->setItemAttr(j, szAttrName.at(j), szAttrVal.at(j)); } pList->push_back(pItem); } return true; } bool OperateItemFile::GetItemArrowFromFile(QString strItemPath, QList<DiagramItem *> *pItemList, QList<Arrow *> *pArrowList, QMenu *itemMenu)
{ if(strItemPath.length() <= 0 || pItemList == NULL || pArrowList == NULL) return false; QDomDocument doc; QFile file(strItemPath); if (!file.open(QIODevice::ReadOnly)){ return false; } if (!doc.setContent(&file)) { file.close(); return false; } QDomNodeList listNormalItem = doc.elementsByTagName("Device"); QDomNodeList listPortItem = doc.elementsByTagName("Port"); QDomNodeList listArrow = doc.elementsByTagName("Arrow"); getNormalItem("Item", pItemList, listNormalItem, itemMenu); getNormalItem("Port", pItemList, listPortItem, itemMenu); for (int i = 0; i < listArrow.size(); i++) { QDomElement arrowEle = listArrow.at(i).toElement(); QString sid = arrowEle.attribute("StartItemId"); QString eid = arrowEle.attribute("EndItemId"); Arrow* pItem = new Arrow(NULL ,NULL); pItem->setItemId(sid,eid); pArrowList->push_back(pItem); } file.close(); return true; } bool OperateItemFile::loadItemToScene(DiagramScene* pScene, bool bIsDialog, QString srcPath)
{ if(!pScene) return false; QList<DiagramItem*> itemList; QList<Arrow*> ArrowList; QString strName; if(bIsDialog) strName = QFileDialog::getOpenFileName(nullptr, QObject::tr("open xml file"), p_globalObject->ProjectPath() + "/" + p_globalObject->getProjectName() ,QObject::tr("XML文件(*XML*)")); else strName = srcPath; //////////////////////////////////////////////////////////////////////////////////// if(!GetItemArrowFromFile(srcPath, &itemList, &ArrowList, NULL)) return false; pScene->ItemClear(); int i=0; for(i=0 ;i<itemList.size() ;i++){ //itemList.at(i)->setBrush(pScene->itemColor()); pScene->addItem(itemList.at(i)); } pScene->setMode(DiagramScene::Mode::MoveItem); //設置箭頭起始節點 int j=0; for(i=0 ;i<ArrowList.size(); i++){ for(j=0 ;j<itemList.size() ;j++){ if(ArrowList.at(i)->getStartId() == itemList.at(j)->getItemId()){ ArrowList.at(i)->setStartItem(itemList.at(j)); break; } } } //設置箭頭結尾節點 for(i=0 ;i<ArrowList.size(); i++){ for(j=0 ;j<itemList.size() ;j++){ if(ArrowList.at(i)->getEndId() == itemList.at(j)->getItemId()){ ArrowList.at(i)->setEndItem(itemList.at(j)); break; } } } for(i=0 ;i<ArrowList.size() ;i++){ if(ArrowList.at(i)->startItem()!=NULL) ArrowList.at(i)->startItem()->addArrow(ArrowList.at(i)); if(ArrowList.at(i)->endItem()!=NULL) ArrowList.at(i)->endItem()->addArrow(ArrowList.at(i)); ArrowList.at(i)->setColor(pScene->lineColor()); ArrowList.at(i)->setZValue(-1000.0); pScene->addItem(ArrowList.at(i)); if(p_globalObject->getCurStatus() == QGlobalObject::devStatus) ArrowList.at(i)->setArrowFlag(true); else ArrowList.at(i)->setArrowFlag(true); ArrowList.at(i)->updatePosition(); } return true; }

  

getNormalItem函數中的type,區分是不是子節點。loadItemToScene 的參數bIsDialog,來確定是否顯示文件對話框。

 

Qt 遍歷不規則樹的節點


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM