QTreeWidget 挂上自定义结构体 (setData)
上篇文章(https://www.cnblogs.com/warmlight/p/12964166.html)说,如果想把示例中的xml信息完全放到树上,那就需要自己做点什么了。那到底要怎么做呢?这里再讨论一下。
示例xml:
1 <?xml version='1.0' encoding='UTF-8'?> 2 <MyItem> 3 <Package Head="check" Desc="" Name="接收数据" Id="9"> 4 <Field Desc="经度" Value="118.244" Type="Float" Name="经度"/> 5 <Field Desc="纬度" Value="42.078105" Type="Float" Name="纬度"/> 6 <Field Desc="高度" Value="8.8" Type="Float" Name="高度"/> 7 <Field Desc="高度1" Value="184.8" Type="Float" Name="高度1"/> 8 </Package> 9 <Package Head="check" Desc="" Name="校正数据" Id="10"> 10 <Field Desc="经度" Value="116.244945" Type="Float" Name="经度"/> 11 <Field Desc="纬度" Value="40.078105" Type="Float" Name="纬度"/> 12 <Field Desc="高度" Value="10.8" Type="Float" Name="高度"/> 13 </Package> 14 <Package Head="send" Desc="" Name="发送数据" Id="11"> 15 <Field Desc="经度" Value="116.244945" Type="Float" Name="经度"> 16 <SubField Desc="则经度" Value="116.244945" Type="Float" Name="经度"> 17 <SubField Desc="zizi经度" Value="116.244945" Type="Float" Name="经度"/> 18 <SubField11 Desc="则经度" Value="116.244945" Type="Float" Name="经度"/> 19 </SubField> 20 </Field> 21 <Field Desc="纬度" Value="40.078105" Type="Float" Name="纬度"/> 22 <Field Desc="高度" Value="10.8" Type="Float" Name="高度"/> 23 </Package> 24 </MyItem>
QTreeWidget导出xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <MyItem> 3 <Package Name="接收数据" Id="9" Head="check" Desc=""> 4 <Field Name="经度" Value="118.244" Desc="经度" Type="Float"/> 5 <Field Name="纬度" Value="42.078105" Desc="纬度" Type="Float"/> 6 <Field Name="高度" Value="8.8" Desc="高度" Type="Float"/> 7 <Field Name="高度1" Value="184.8" Desc="高度1" Type="Float"/> 8 </Package> 9 <Package Name="校正数据" Id="10" Head="check" Desc=""> 10 <Field Name="经度" Value="116.244945" Desc="经度" Type="Float"/> 11 <Field Name="纬度" Value="40.078105" Desc="纬度" Type="Float"/> 12 <Field Name="高度" Value="10.8" Desc="高度" Type="Float"/> 13 </Package> 14 <Package Name="发送数据" Id="11" Head="send" Desc=""> 15 <Field Name="经度" Value="116.244945" Desc="经度" Type="Float"> 16 <SubField Name="经度" Value="116.244945" Desc="则经度" Type="Float"> 17 <SubField Name="经度" Value="116.244945" Desc="zizi经度" Type="Float"/> 18 <SubField11 Name="经度" Value="116.244945" Desc="则经度" Type="Float"/> 19 </SubField> 20 </Field> 21 <Field Name="纬度" Value="40.078105" Desc="纬度" Type="Float"/> 22 <Field Name="高度" Value="10.8" Desc="高度" Type="Float"/> 23 </Package> 24 </MyItem>
我没观察一下原xml,根节点无属性,其他节点的属性也比较单一,分为两种。那就定义两个结构体吧。如果你的节点有更多的属性,我想你就要考虑是不是换其他方法了。
在ManageTreeXml.h中,添加两个结构体:
1 struct PackageItem : public QObjectUserData { 2 QString head; 3 QString name; 4 QString desc; 5 QString id; 6 }; 7 Q_DECLARE_METATYPE(PackageItem) 8 9 struct FieldItem : public QObjectUserData { 10 QString desc; 11 QString name; 12 QString value; 13 QString type; 14 }; 15 Q_DECLARE_METATYPE(FieldItem)
一定要注意使用Q_DECLARE_METATYPE宏。
这里是在基础代码上增加的。基础代码和请查看:https://www.cnblogs.com/warmlight/p/12964166.html
加载xml文件时,需要做一些处理。这里修改SetTreeNodeText函数
1 void ManageTreeXml::setTreeNodeText(QDomNode Node ,QTreeWidgetItem* treeNode) 2 { 3 if(treeNode == NULL) return; 4 5 QDomElement nodeEle = Node.toElement(); 6 QString tagName =nodeEle.tagName(); 7 treeNode->setText(0 ,tagName); 8 if(tagName.compare("Package") == 0){ 9 PackageItem item; 10 item.desc = nodeEle.attribute("Desc"); 11 item.head = nodeEle.attribute("Head"); 12 item.id = nodeEle.attribute("Id"); 13 item.name = nodeEle.attribute("Name"); 14 treeNode->setData(0, Qt::UserRole + 1, QVariant::fromValue(item)); 15 } 16 else if(tagName.compare("Field") == 0 || 17 tagName.compare("SubField") == 0 || 18 tagName.compare("SubField11") == 0){ 19 FieldItem item; 20 item.desc = nodeEle.attribute("Desc"); 21 item.value = nodeEle.attribute("Value"); 22 item.type = nodeEle.attribute("Type"); 23 item.name = nodeEle.attribute("Name"); 24 treeNode->setData(0, Qt::UserRole + 1, QVariant::fromValue(item)); 25 } 26 // qDebug() << "ItemText:" << Node.toElement().tagName(); 27 28 QString treeType = TREE_PACKAGE_TYPE; 29 if(treeType == TREE_LINK_TYPE) 30 { 31 // treeNode->setText(1 ,Node.toElement().attribute("portName")); 32 // treeNode->setText(2 ,Node.toElement().attribute("portDesc")); 33 // treeNode->setText(3 ,Node.toElement().attribute("portType")); 34 // treeNode->setText(4 ,Node.toElement().attribute("portIP")); 35 // treeNode->setText(5 ,Node.toElement().attribute("portOrBaudRate")); 36 } 37 else if(treeType == TREE_PACKAGE_TYPE) 38 { 39 // treeNode->setText(1 ,Node.toElement().attribute("Value")); 40 // treeNode->setText(2 ,Node.toElement().attribute("Name")); 41 // treeNode->setText(3 ,Node.toElement().attribute("Index")); 42 // treeNode->setText(4 ,Node.toElement().attribute("Type")); 43 // treeNode->setText(5 ,Node.toElement().attribute("Len")); 44 // treeNode->setText(6 ,Node.toElement().attribute("Desc")); 45 } 46 }
保存xml文件时,增加函数SetDomEleAttribute,并在SaveItem中调用。
1 void ManageTreeXml::SaveItem(QDomElement& root, QTreeWidgetItem *item, QDomDocument& doc) 2 { 3 int countChild = item->childCount(); 4 for (int i = 0; i < countChild; i++) 5 { 6 QTreeWidgetItem *childItem = item->child(i); 7 QString itemTxt = childItem->text(0); 8 QDomElement ele = doc.createElement(itemTxt); 9 SetDomEleAttribute(ele, childItem); 10 root.appendChild(ele); 11 12 SaveItem(ele,childItem,doc); 13 } 14 } 15 16 void ManageTreeXml::SetDomEleAttribute(QDomElement &ele, QTreeWidgetItem *item) 17 { 18 QString itemTxt = item->text(0); 19 if(itemTxt.compare("Package") == 0){ 20 PackageItem packItem = item->data(0, Qt::UserRole + 1).value<PackageItem>(); 21 ele.setAttribute("Head", packItem.head); 22 ele.setAttribute("Desc", packItem.desc); 23 ele.setAttribute("Name", packItem.name); 24 ele.setAttribute("Id", packItem.id); 25 } 26 else if (itemTxt.compare("Field") == 0 || 27 itemTxt.compare("SubField") == 0 || 28 itemTxt.compare("SubField11") == 0 ) { 29 FieldItem fieldItem = item->data(0, Qt::UserRole + 1).value<FieldItem>(); 30 ele.setAttribute("Value", fieldItem.value); 31 ele.setAttribute("Desc", fieldItem.desc); 32 ele.setAttribute("Name", fieldItem.name); 33 ele.setAttribute("Type", fieldItem.type); 34 } 35 }
这样保存的xml和源xml就完全一致了。
xml文件不同的话,要根据个人情况修改。