Qt通过读取XML文件,绘制图形界面

最近需要实现通过读取xml文件的形式动态绘制界面的需求,这样会很方便,在外界修改xml文件就可以了,不需要重新编译程序。

一:XML文件
XML的格式和一些说明,本文就不在介绍了,菜鸟教程有更清晰的入门介绍:菜鸟教程_XML

二:QT中读取XML的类和常用函数
QT中提供了一个读取XML文件的类:QXmlStreamReader
头文件:

#include <QXmlStreamReader>

这个类在使用时会创建一个读取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

<?xml version ="1.0" encoding ="utf-8"?>
<MSG>
  <Button id ="main_interface">
    <title>
	  <Name>主界面</Name>
      <Width>90</Width>
      <Height>40</Height>
      <Xcoordinate>250</Xcoordinate>
      <Ycoordinate>250</Ycoordinate>
    </title>
  </Button> 
</MSG>

2,新建一个config文件
config.h

#ifndef CONFIG_H
#define CONFIG_H
#include <QXmlStreamReader>
#include <QFile>
#include <QApplication>
#include <QDir>
#include <QDebug>

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 <QMainWindow>
#include <QPushButton>
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 <QDebug>
#include <QCheckBox>
#include <qlistwidget.h>
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 <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

五:运行结果
在这里插入图片描述
六:结语
这个并不是通用的,仅供参考,每个人都要自己写一个适合自己的祖传代码,这样以后复用性很高。

  • 5
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路漫漫其远,吾求索

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值