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 遍历不规则树的节点

posted @ 2020-01-02 15:50  阳光下的小土豆  阅读(2645)  评论(0编辑  收藏  举报