最近需要实现通过读取xml文件的形式动态绘制界面的需求,这样会很方便,在外界修改xml文件就可以了,不需要重新编译程序。
一:XML文件
XML的格式和一些说明,本文就不在介绍了,菜鸟教程有更清晰的入门介绍:菜鸟教程_XML
二:QT中读取XML的类和常用函数
QT中提供了一个读取XML文件的类:QXmlStreamReader
头文件:
#include
这个类在使用时会创建一个读取xml文件的迭代器
QXmlStreamReader xmlReader(&filename); //xmlReader就是一个迭代器
该类常见的一些接口函数:
readNextStartElement();//挨个读入节点
isStartElement();//判断节点的开始
isEndElement();//判断节点的结束
name();//得到当前节点的名字
readElementText();//访问当前节点的内容
attributes();//获取还有属性节点的属性
atEnd();//判断XML文件是否结束
hasError();//判断XML文件是否出错
三:代码思路
XML文件实际上就是一个树状结构,所以需要一段一段的去读,先设置一个迭代器,找到根节点,然后去寻找根节点下面的内容,然后再对根节点中的内容进行判定,符合条件的执行代码,取出你想取出的数据,如果不需要就直接跳过,读完一个节点的内容接着转到下一个节点去,就是读完左节点再到中间节点,直到将根节点遍历结束,就是读完XML文件。
代码模式:
if(xmlReader.name() == "根节点名字" && xmlReader.isStartElement())
{
xmlReader.readNextStartElement();
while(!(xmlReader.name() == "根节点名字" && xmlReader.isEndElement())
{
xmlReader.readNextStartElement();
if(xmlReader.name() == "节点名字1" && xmlreader.isStartElement())
{
while(!(xmlReader.name() == "节点名字1" && xmlReader.isEndElement())
{ ...... }
}
else if(xmlReader.name() == "节点名字2" && xmlreader.isStartElement())
{
while(!(xmlReader.name() == "节点名字2" && xmlReader.isEndElement())
{ ...... }
}
}
}
四:代码实现
1,准备一个XMl文档:
testconfig.xml
<MSG>
<Button id ="main_interface">
<title>
<Name>主界面Name>
<Width>90Width>
<Height>40Height>
<Xcoordinate>250Xcoordinate>
<Ycoordinate>250Ycoordinate>
title>
Button>
MSG>
2,新建一个config文件
config.h
#ifndef CONFIG_H
#define CONFIG_H
#include
#include
#include
#include
#include
class config
{
public:
config();
//读取XML文件,并存到一个list容器里面
QStringList readConfig();
};
#endif // CONFIG_H
config.cpp
#include "config.h"
config::config()
{
}
QStringList config::readConfig()
{
//需要打开的文件
QFile file;
//节点的名字
QString nodename;
//最终输出的内容
QStringList OutPut;
//打开文件路径
file.setFileName(qApp->applicationDirPath()+"/test_xml/testconfig.xml");
if (!file.exists())
{
qDebug() << "testconfig.xml文件不存在";
}
else
{
qDebug() << "testconfig.xml文件存在";
}
//打开文件
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug()<<"打开文件失败!";
}
else
{
//读取xml文件的迭代器
QXmlStreamReader xmlreader(&file);
qDebug() << "testconfig.xml文件存在,且打开文件成功!";
//当文件没有结束且没有出错执行下面的代码
while(!xmlreader.atEnd() || !xmlreader.hasError())
{
//找到非根节点下的第一个子节点
xmlreader.readNextStartElement();
//第一个子节点Button
nodename = xmlreader.name().toString();
//如果是第一个子节点的开始执行下列代码
if(nodename == "Button" && xmlreader.isStartElement())
{
//读取出附加信息
xmlreader.attributes().value("id").toString();
//添加到输出的字符串里
OutPut.append(QString("%1").arg(xmlreader.attributes().value("id").toString()));
//如果子节点中的内容没有结束
while(!(nodename == "Button" && xmlreader.isEndElement()))
{
//挨个读入节点
xmlreader.readNextStartElement();
nodename = xmlreader.name().toString();
if(nodename == "Name" && xmlreader.isStartElement())
{
while(!(nodename == "Name" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
}
}
else if(nodename == "Xcoordinate" && xmlreader.isStartElement())
{
while(!(nodename == "Xcoordinate" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
}
}
else if(nodename == "Ycoordinate" && xmlreader.isStartElement())
{
while(!(nodename == "Ycoordinate" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
}
}
else if(nodename == "Width" && xmlreader.isStartElement())
{
while(!(nodename == "Width" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
}
}
else if(nodename == "Height" && xmlreader.isStartElement())
{
while(!(nodename == "Height" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
}
}
}
}
}
file.close();
qDebug()<<"文件关闭"<<endl;
qDebug()<<"xml文件读取完成"<<endl;
return OutPut;
}
}
3,在mainwindow里面绘制界面
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "config.h"
#include
#include
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
config config;
QStringList str;
str = config.readConfig();
for (int i = 0; i<str.count();i++)
{
qDebug()<<str.at(i)<<endl;
}
QPushButton *aa = new QPushButton(this);
aa->setText(str.at(1));
aa->setGeometry(str.at(5).toInt(),str.at(4).toInt(),str.at(2).toInt(),str.at(3).toInt());
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}