Qt 遍历不规则树的节点
在使用Qt的GraphicsScene作图时,遇到类似这样的需求:在scene中创建节点类似下图,
现在我要把每个节点的txt保存到xml文件中,结构为
<?xml version='1.0' encoding='UTF-8'?>
<root>
<A>
<B>
</B>
<C>
<E>
...
</E>
</C>
<D>
<F>
...
</F>
</D>
</A>
</root>
并且,还要能根据xml文件将这个结构还原出来(由于没有保存坐标信息,当然不能恢复原状)。
我将过程分为:遍历,保存xml;读取xml,还原图形。
我使用Qt的示例项目DiagramScene来改造。
首先,起始节点要与其他节点有所不同,便于我们区分。diagramitem类中,DiagramType { Step, Conditional, StartEnd, Io };,我添加一个virStep类型作为开始节点,其他节点类型为Step。其实virStep和Step的图形一模一样,只是类型不同。
在DiagramItem类中增加一些成员
QList<Arrow *> getArrow(){return arrows;}
void setText(QString text){ mText = text;}
void setItemId(QString pid){ ItemId = pid;}//唯一标识,在创建时设置
QString getItemId(){return ItemId;}
QString getText(){ return mText; }
重写其paint函数,在其中添加:
painter->drawText(boundingRect() , Qt::AlignCenter ,mText);
保存:
bool OperateItemFile::SaveRelationship(QList<DiagramItem *> &listItem, QList<Arrow *> &listArrow)
{
QFileDialog dlg;
dlg.setAcceptMode(QFileDialog::AcceptSave);
QString strName = dlg.getSaveFileName(getMainWindow() ,QObject::tr("save xml file"), "" ,QObject::tr("XML文件(*.XML)"));
if(strName.isEmpty())
return false; QDomDocument doc;
doc.appendChild( doc.createProcessingInstruction("xml", XML_HEAD_INFO));
QFile file(strName);
if (!file.open(QIODevice::WriteOnly)){
return false;
}
QDomElement root = doc.createElement("Root");
doc.appendChild(root); DiagramItem* startItem = NULL ;
QDomElement startEle;
for (int i = 0; i < listItem.size(); i++) {
if(listItem.at(i)->diagramType() == DiagramItem::virStep){
//开始节点
startEle = doc.createElement(listItem.at(i)->getText());
root.appendChild(startEle);
startItem = listItem.at(i);
//listItem.removeAt(i);
break;
}
} if(!startItem) return false; TravelAllItem(startItem, doc, startEle, listItem); QString xml = doc.toString();
QTextStream txtOutput(&file);
txtOutput.setCodec("UTF-8");
txtOutput<<xml;
file.close(); return true;
} void OperateItemFile::GetSubItems(DiagramItem *item, QList<DiagramItem*>& listNodeItem)
{
if(!item) return; listNodeItem.clear();
QList<Arrow*> listArrow = item->getArrow();
for (int i = 0; i < listArrow.size(); i++) {
if(listArrow.at(i)->startItem() == item){
listNodeItem.push_back(listArrow.at(i)->endItem());
}
}
} void OperateItemFile::TravelAllItem(DiagramItem *rootItem, QDomDocument &doc, QDomElement &rootEle, QList<DiagramItem *> &listItem)
{
if(listItem.size() < 1)
return;
QList<DiagramItem*> listNodeItem;
GetSubItems(rootItem, listNodeItem);
for (int i = 0; i < listNodeItem.size(); i++) {
QDomElement ele = doc.createElement(listNodeItem.at(i)->getText());
rootEle.appendChild(ele);
listItem.removeOne(rootItem);
TravelAllItem(listNodeItem.at(i), doc, ele, listItem); } }
使用GraphicsScene的selectItems函数,从中分别获得diagramitem和arrow。代码如果编译不通,可根据情况修改。
读入xml:
void OperateItemFile::ImportTargetFile(DiagramScene* pScene)
{
QString strName;
strName = QFileDialog::getOpenFileName(nullptr, QObject::tr("open xml file"), p_globalObject->ProjectPath() + "/" + p_globalObject->getProjectName() ,QObject::tr("XML文件(*XML*)"));
if(strName.isEmpty()){
return;
} QDomDocument doc;
QFile file(strName);
if (!file.open(QIODevice::ReadOnly)){
return ;
}
if (!doc.setContent(&file))
{
file.close();
return ;
} QDomNode domNodeStart = doc.documentElement();
QList<DiagramItem*> listItem;
QList<Arrow*> listArrow;
m_bStartNode = true;
SetItemPos(pScene->sceneRect().center());
parsePackage(domNodeStart, listItem, listArrow); pScene->ItemClear(); int i=0;
for(i=0 ;i<listItem.size() ;i++){
pScene->addItem(listItem.at(i));
}
pScene->setMode(DiagramScene::Mode::MoveItem);
////////////////////////////////////////////////////////////////////////////////////
//设置箭头起始节点
int j=0;
for(i=0 ;i<listArrow.size(); i++){
for(j=0 ;j<listItem.size() ;j++){
if(listArrow.at(i)->getStartId() == listItem.at(j)->getItemId()){
listArrow.at(i)->setStartItem(listItem.at(j));
break;
}
}
}
//设置箭头结尾节点
for(i=0 ;i<listArrow.size(); i++){
for(j=0 ;j<listItem.size() ;j++){
if(listArrow.at(i)->getEndId() == listItem.at(j)->getItemId()){
listArrow.at(i)->setEndItem(listItem.at(j));
break;
}
}
} for(i=0 ;i<listArrow.size() ;i++){
if(listArrow.at(i)->startItem()!=NULL)
listArrow.at(i)->startItem()->addArrow(listArrow.at(i)); if(listArrow.at(i)->endItem()!=NULL)
listArrow.at(i)->endItem()->addArrow(listArrow.at(i)); listArrow.at(i)->setColor(pScene->lineColor());
listArrow.at(i)->setZValue(-1000.0);
pScene->addItem(listArrow.at(i));
if(p_globalObject->getCurStatus() == QGlobalObject::devStatus)
listArrow.at(i)->setArrowFlag(true);
else
listArrow.at(i)->setArrowFlag(true);
listArrow.at(i)->updatePosition();
} file.close();
} bool OperateItemFile::parsePackage(QDomNode pNode, QList<DiagramItem*>& listItem, QList<Arrow*>& listArrow)
{
QDomNode myNode = pNode.firstChild();
while(!myNode.isNull()){
QDomElement domE = myNode.toElement();
QString qstrTagName = domE.tagName();
myDebug(qstrTagName);
if(qstrTagName.compare(PackageRoot) != 0 && !qstrTagName.isEmpty()) {
DiagramItem* pItem = NULL;
if(m_bStartNode){
pItem = new DiagramItem(DiagramItem::virStep ,NULL);
domE.setAttribute("StartItem", "true");
m_bStartNode = false;
}
else {
pItem = new DiagramItem(DiagramItem::Step ,NULL);
}
pItem->setPos(m_itemPos);
m_itemPos = GetNextItemPos(m_itemPos);
//pItem->setZValue(z.toFloat());
pItem->setBkColor(QColor(4294967295));
pItem->setItemId(p_globalObject->getGUID());
pItem->setText(qstrTagName);
pItem->setBrush(QBrush(4294967295, (Qt::BrushStyle)1));
domE.setAttribute("ItemId", pItem->getItemId());
if(!domE.hasAttribute("StartItem")){
Arrow* pArrow = new Arrow(NULL, NULL);
QString startItemId = pNode.toElement().attribute("ItemId");
QString endItemId = pItem->getItemId();
pArrow->setItemId(startItemId, endItemId);
listArrow.push_back(pArrow);
}
listItem.push_back(pItem);
} parsePackage(myNode, listItem, listArrow); myNode = myNode.nextSibling();
}
return true;
} QPointF OperateItemFile::GetNextItemPos(QPointF preItemPos)
{
float rat = 1;
qreal x = preItemPos.x()+80;
qreal y = x*rat;
QPointF pt(x,y);
return pt;
}
先写到这里,下一篇将写一下,如何完全还原图形。
Qt 遍历不规则树的节点的更多相关文章
- SAX解析xml (遍历DOM树各节点)
本文参考 http://yangjunfeng.iteye.com/blog/401377 1. books.xml <?xml version="1.0" encoding ...
- Qt实现表格树控件-自绘树节点虚线
目录 一.开心一刻 二.自绘树节点? 三.效果展示 四.实现思路 1.可扩展接口 2.函数重写 3.同步左侧表头 五.相关文章 原文链接:Qt实现表格树控件-自绘树节点虚线 一.开心一刻 一程序员第一 ...
- POJ 3321 Apple Tree(后根遍历将树转化成序列,用树状数组维护)
题意:一棵树,有很多分叉,每个分叉上最多有1个苹果. 给出n,接下来n-1行,每行u,v,表示分叉u,v之间有树枝相连.这里数据中u相当于树中的父节点,v相当于子节点. 给出两个操作: 1.C x ...
- 根据 中序遍历 和 后序遍历构造树(Presentation)(C++)
好不容易又到周五了,周末终于可以休息休息了.写这一篇随笔只是心血来潮,下午问了一位朋友PAT考的如何,顺便看一下他考的试题,里面有最后一道题,是关于给出中序遍历和后序遍历然后求一个层次遍历.等等,我找 ...
- 函数遍历DOM树
//获取页面中的根节点--根标签 var root=document.documentElement;//html //函数遍历DOM树 //根据根节点,调用fn的函数,显示的是根节点的名 ...
- 探索未知种族之osg类生物---状态树与渲染树以及节点树之间的关系
节点树 首先我们来看一个场景构建的实例,并通过它来了解一下“状态节点”StateGraph 和“渲染叶”RenderLeaf 所构成的状态树,“渲染台”RenderStage 和“渲染元”Render ...
- 先序遍历DOM树的5种方法
DOM树由文档中的所有节点(元素节点.文本节点.注释节点等)所构成的一个树结构,DOM树的解析和构建是浏览器要实现的关键功能.既然DOM树是一个树结构,那么我们就可以使用遍历树结构的相关方法来对DOM ...
- 利用层序遍历(含空节点)和中序遍历重建二叉树 python
给定一颗二叉树的层序遍历(不含None的形式)和中序遍历序列,利用两个序列完成对二叉树的重建. 还是通过一个例子来说明整个过程,下图所示的二叉树,层序遍历结果为[a,b,c,d,e],中序遍历结果为[ ...
- 九度OJ 1359:大魏树遍历 (树)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:299 解决:29 题目描述: 大魏是JOBDU技术组里最喜欢折腾的一个了,单反.骑车.改九度页面,当然还有YY prado.我们姑且先把这些 ...
随机推荐
- 网络吞吐量(network)
题目 分析 过一遍spfa,把从点1到其他每一个点的最短路求出来, 接着递归把所有最短路径上的路径保留,其他的删掉. 对于保留的路径作为网络流的边,流量为无穷大,对于每个点拆点两个点之间的流量为吞吐量 ...
- 对TypeScript进行研究
1.npm install -g typescript 在编辑器,将下面的代码输入到greeter.ts文件里: function greeter(person) { return "Hel ...
- 浙大PAT CCCC L3-001 凑零钱 ( 0/1背包 && 路径记录 )
题目链接 分析 : 就是一个 0/1 背包,但是需要记录具体状态的转移情况 这个可以想象成一个状态转移图,然后实际就是记录路径 将状态看成点然后转移看成边,最后输出字典序最小的路径 这里有一个很巧妙的 ...
- Cloud Computing——Everything as a Service
service 分类 有Iaas, Paas, SaaS HDFS 总结☞: HDFS应付不了的场景 无法低时延 小文件存储存在空间利用率问题 文件不可修改 三副本有什么作用 防止单机故障,提高可用性 ...
- PCL智能指针疑云 <一>
背景: 最近写了一个包,使用ndt算法拼接点云,构建三维壁面环境的点云地图. 设计一个lidar类,表征激光雷达.可以获取点云数据并存储到容器 std::vector<PointCloudPtr ...
- 苹果CMSv10对接微信公众号教程
首先声明下,对接公众号的话需要自行注册公众号“订阅号” 对接失败的原因大多是域名变红导致!简单的测试方法就是把域名链接发给qq好友或是qq群里看看有没有变红 域名变红以后大概率不会对接成功的,请知悉 ...
- 命令行创建 vue 项目(仅用于 Vue 2.x 版本)
1 .安装 Node.js 和 npm ( 验证安装成功输入下图 1 命令行可得 2:输入命令行 3 可得 4 即安装成功) 2.安装全局 webpack (安装依照下图输入命令行 1 耐心等待至到出 ...
- pyCharm报错"your evaluation license has expired, pycharm will now exit"解决方法(实测)
一.修改C:\Windows\System32\drivers\etc 目录下的hosts文件 1.打开hosts文件,路径是 c:\windows\system32\drivers\etc\host ...
- 【Python】学习笔记十二:模块
模块(module) 在Python中,一个.py文件就是一个模块.通过模块,你可以调用其它文件中的程序 引入模块 先写一个first.py文件,内容如下: def letter(): print(' ...
- Using FileUpload
Using FileUpload FileUpload can be used in a number of different ways, depending upon the requiremen ...