QT之天气预报

1. HTTP基本概念

• HTTP(超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是万维网(WWW)的数据通信的基础。了解HTTP的基本概念对于理解现代网络通信至关重要。以下是HTTP的一些核心概念:
1.**请求和响应:
HTTP是一个
基于请求****-** 响应模式的协议客户端(通常是Web浏览器)向服务器发送一个HTTP请求,然后服务器返回一个HTTP响应。**请求包含请求的资源(如网页),而响应包含请求的资源的内容。
**2. HTTP
方法:

HTTP定义了一系列的方法来表明对资源的不同操作,最常用的包括:
GET: 用于请求资源。
POST: 用于提交数据给服务器(例如,表单数据)。
PUT: 用于上传文件或内容。
DELETE: 用于请求删除资源。
HEAD : 用于获取资源的元信息,而不是资源本身
3.**状态码:
服务器对
请求的响应中包含一个状态码**,它表示请求的成功或失败,以及失败的原因。常见的状态码包括:
200 OK: 请求成功。
404 Not Found: 请求的资源未找到。
500 Internal Server Error: 服务器内部错误。
301 Moved Permanently: 请求的资源已永久移动到新位置。
4. URL(统一资源定位符):
URL是Web 上资源的地址。它指定了资源的位置以及用于访问资源的协议(例如,http://)。
**5. HTTP
**头:

HTTP请求和响应包含头部信息,这些信息包括元数据,如内容类型、内容长度、服务器信息、客户端信息等。例如, Content-Type 头部指示响应中的媒体类型(如text/html,application/json)。
6.**无状态协议:
HTTP是一个
无状态协议** ,这意味着服务器不会保留任何请求的数据(状态)。然而,通过使用如
Cookies这样的机制,可以在多个请求之间维持状态。
7.**安全性(HTTPS):
HTTPS是HTTP的安全版本,它在HTTP和TCP层之间增加了
一个加密层(通常是SSL/TLS** 。这提供了数据传输的加密和更好的安全性
8. RESTful API:
RESTful是一种使用HTTP协议的Web服务设计风格,它利用HTTP的方法来实现API的不同操作。在 RESTful架构中,**每个
URL代表一个资源,并使用HTTP的方法(如GET, POST)来处理这些资源。**
9. SessionCookies:
由于HTTP本身是无状态的,Cookies和会话(Session)被用来在多个请求之间存储用户数据,从而为用户提供连贯的体验。

2. QT的HTTP编程

• Qt中的HTTP编程主要涉及使用Qt的网络模块来进行HTTP请求和处理HTTP响应。Qt提供了一系列类来处理网络通信,其中最常用的类是 QNetworkAccessManager**、 QNetworkRequest 、** QNetworkReply 以及相关的支持类。

3. 代码

3.1 在widget.cpp

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

#include <QMenu>
#include <QDebug>
#include <QMessageBox>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QPainter>
#include <QtNetwork/QNetworkAccessManager>

void Widget::mousePressEvent(QMouseEvent *event){
    //关闭窗口
    if(event->button() == Qt::RightButton){
         qDebug() << "right Mouse click";
         menuQuit->exec(QCursor::pos());//启动菜单栏,menu出现在鼠标当前位置
    }

    //关键是获得当前鼠标位置,当前窗口位置,新的窗口位置
    //移动窗口(通过初始鼠标的位置减去初始窗口的位置,得到位移值)
    //然后在通过新的鼠标位置 - 位移值 = 新的窗口位置
    if(event->button() == Qt::LeftButton){
        qDebug() << "left Mouse click";
//        qDebug() << "鼠标当前在全局的位置" << event->globalPos();//返回的是鼠标事件的全局坐标
//        qDebug() << "返回的是当前对象(窗口或部件)在其父容器中的位置" << this->pos(); // 返回的是当前对象(窗口或部件)在其父容器中的位置
//        qDebug()  << event->globalPos() - this->pos();//返回的是QPoint类型,这是当前鼠标位置和当前窗口位置的差值

        moffset = event->globalPos() - this->pos();
    }

}

//鼠标左键按下后的移动,导致这个事件被调用,设置窗口的新位置
void Widget::mouseMoveEvent(QMouseEvent *event){
    //这是移动窗口

    //    1.当鼠标按下的时候,获得当前鼠标和当前窗口的那段偏移值
    //    2.当我鼠标拖动的时候,根据偏移值,算出新的窗口该有的位置
    this->move(event->globalPos() - moffset);
}

bool Widget::eventFilter(QObject *object, QEvent *event)
{
    //判断监控对象是widget0404,并且触发的事件类型是QEvent::Paint
    if(object == ui->widget0404 && event->type() == QEvent::Paint){
        drawTempLineHigh();
        return true;//表示事件应被处理
    }

    if(object == ui->widget0405 && event->type() == QEvent::Paint){
        drawTempLineLow();
        return true;
    }
    return QWidget::eventFilter(object,event);
}
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //界面初始化
    setFixedSize(585,962);


    //去除上方"打叉关闭"那一行(设置无状态栏)
    setWindowFlag(Qt::FramelessWindowHint);

    //使用QMenu创建下拉菜单或上下文菜单(右键菜单),来关闭窗口
    menuQuit = new QMenu(this);
    //QAction代表用户可以执行的具体操作,创建关闭的动作
    QAction* closeAct = new QAction(QIcon(":/res/close.png"),tr("关闭"),this);
    //把closeAct操作,添加到menuQuit里面
    menuQuit->addAction(closeAct);
    //美化QMenu,设置菜单项文字颜色
    //closeAct = new QAction(QIcon(":/res/search.png"), tr("打开"), this);
    //menuQuit->addAction(closeAct);//通过这个验证QMenu也是个菜单。
    menuQuit->setStyleSheet("QMenu::item {color:white}");
    //创建信号,当菜单中的某个动作被触发(比如用户点击了菜单项)时,这个信号会被发射。
    connect(menuQuit,&QMenu::triggered,this,[=]{
       //关闭窗口
       this->close();
    });

    //管理所有的网络请求和连接
    //在当前窗口,使用QNetworkAccessManager发起get请求
    manager = new QNetworkAccessManager(this);
    //指定请求的url地址
    urlStr = "http://gfeljm.tianqiapi.com/api?unescape=1&version=v9&appid=47132967&appsecret=u8MRztWQ";
    //放入QUrl
    //urlStr = "";
    QUrl tianqiUrl(urlStr);
    //指定请求的url地址(封装HTTP请求的配置信息)
    QNetworkRequest res(tianqiUrl);

    //进行get请求
    //获取服务器返回的数据
    //QNetworkReply(网络响应),处理服务器返回的数据
    reply = manager->get(res);

    //绑定信号与槽
    //当通过 QNetworkAccessManager 发起的任何网络请求完成后,都会触发此信号(无论成功还是失败都会触发)。
    connect(manager,&QNetworkAccessManager::finished,this,&Widget::readHttpReply);


    //把所有天气的图标放进map里面
    //根据keys,设置icon的路径
    //:/res/type/BaoXue.png
    mTypeMap.insert("暴雪",":/res/type/BaoXue.png");
    mTypeMap.insert("暴雨",":/res/type/BaoYu. png");
    mTypeMap.insert("暴雨到大暴雨",":/res/type/BaoYuDaoDaBaoYu.png");
    mTypeMap.insert("大暴雨",":/res/type/DaBaoYu.png");
    mTypeMap.insert("大暴雨到特大暴雨",":/res/type/DaBaoYuDaoTeDaBaoYu.png");
    mTypeMap.insert("大到暴雪",":/res/type/DaDaoBaoXue.png");
    mTypeMap.insert("大雪",":/res/type/DaXue.png");
    mTypeMap.insert("大雨",":/res/type/DaYu.png");
    mTypeMap.insert("冻雨",":/res/type/DongYu.png");
    mTypeMap.insert("多云",":/res/type/DuoYun.png");
    mTypeMap.insert("浮沉",":/res/type/FuChen.png");
    mTypeMap.insert("雷阵雨",":/res/type/LeiZhenYu.png");
    mTypeMap.insert("雷阵雨伴有冰雹",":/res/type/LeiZhenYuBanYouBingBao.png");
    mTypeMap.insert("霾",":/res/type/Mai.png");
    mTypeMap.insert("强沙尘暴",":/res/type/QiangShaChenBao.png");
    mTypeMap.insert("晴",":/res/type/Qing.png");
    mTypeMap.insert("沙尘暴",":/res/type/ShaChenBao.png");
    mTypeMap.insert("特大暴雨",":/res/type/TeDaBaoYu.png");
    mTypeMap.insert("undefined",":/res/type/undefined.png");
    mTypeMap.insert("雾",":/res/type/Wu.png");
    mTypeMap.insert("小到中雪",":/res/type/XiaoDaoZhongXue.png");
    mTypeMap.insert("小到中雨",":/res/type/XiaoDaoZhongYu.png");
    mTypeMap.insert("小雪",":/res/type/XiaoXue.png");
    mTypeMap.insert("小雨",":/res/type/XiaoYu.png");
    mTypeMap.insert("雪",":/res/type/Xue.png");
    mTypeMap.insert("扬沙",":/res/type/YangSha.png");
    mTypeMap.insert("阴",":/res/type/Yin.png");
    mTypeMap.insert("雨",":/res/type/Yu.png");
    mTypeMap.insert("雨夹雪",":/res/type/YuJiaXue.png");
    mTypeMap.insert("阵雪",":/res/type/ZhenXue.png");
    mTypeMap.insert("阵雨",":/res/type/ZhenYu.png");
    mTypeMap.insert("中到大雪",":/res/type/ZhongDaoDaXue.png");
    mTypeMap.insert("中到大雨",":/res/type/ZhongDaoDaYu.png");
    mTypeMap.insert("中雪",":/res/type/ZhongXue.png");
    mTypeMap.insert("中雨",":/res/type/ZhongYu.png");


    //把UI的控件存在一个数组里面
    mDateList << ui->labelday0 << ui->labelday1
              << ui->labelday2 << ui->labelday3
              << ui->labelday4 << ui->labelday5;


    mWeekList << ui->labelDate0 << ui->labelDate1
              << ui->labelDate2 << ui->labelDate3
              << ui->labelDate4 << ui->labelDate5;


    mIconList << ui->labelWheatherIcon0 << ui->labelWheatherIcon1
              << ui->labelWheatherIcon2 << ui->labelWheatherIcon3
              << ui->labelWheatherIcon4 << ui->labelWheatherIcon5;


    mWeaTypeList << ui->lbwheatherTypeDate0 << ui->lbwheatherTypeDate1
              << ui->lbwheatherTypeDate2 << ui->lbwheatherTypeDate3
              << ui->lbwheatherTypeDate4 << ui->lbwheatherTypeDate5;

    mAirqList << ui->labelairq0 << ui->labelairq1
              << ui->labelairq2 << ui->labelairq3
              << ui->labelairq4 << ui->labelairq5;

    mFxList << ui->labelFX0 << ui->labelFX1
              << ui->labelFX2 << ui->labelFX3
              << ui->labelFX4 << ui->labelFX5;

    mFlList << ui->labelFL0 << ui->labelFL1
              << ui->labelFL2 << ui->labelFL3
              << ui->labelFL4 << ui->labelFL5;


    //安装事件过滤器
    ui->widget0404->installEventFilter(this);
    ui->widget0405->installEventFilter(this);
}

void Widget::parseWeatherJsonDataNew(QByteArray rawData){
    //将字符数组的数据转变为json格式
    //将原始的二进制/文本数据解析为Qt的JSON文档对象,方便后续处理JSON数据
    QJsonDocument jsonObj = QJsonDocument::fromJson(rawData);

    //处理数据
    if(!jsonObj.isNull() && jsonObj.isObject()){//jsonObj必须是对象而且必须不能空
        //将jsonObj转换为object对象
        QJsonObject jsonRoot = jsonObj.object();

        //填充days里面只显示一天的数据
        days[0].mCity = jsonRoot["city"].toString();
        days[0].mPm25 = jsonObj["aqi"].toObject()["pm25"].toString();

        //填充需要七天的数据
        if(jsonRoot.contains("data") && jsonRoot["data"].isArray()){
            //转换为Array
            QJsonArray weaArray = jsonRoot["data"].toArray();
            for(int i = 0;i < weaArray.size();i++){
                //在转变为Object,因为数组里面的每一项都是对象
                QJsonObject obj = weaArray[i].toObject();
                days[i].mFl = obj["win_speed"].toString();
                days[i].mFx = obj["win"].toArray()[0].toString();
                days[i].mHu = obj["humidity"].toString();

                days[i].mTip = obj["index"].toArray()[3].toObject()["desc"].toString();

                days[i].mAirq = obj["air_level"].toString();
                days[i].mDate = obj["date"].toString();
                days[i].mTemp = obj["tem"].toString();

                days[i].mWeek = obj["week"].toString();
                days[i].mTempLow = obj["tem2"].toString();
                days[i].mTempHigh = obj["tem1"].toString();
                days[i].mWeatherType = obj["wea"].toString();

            }
            updateUI();//更新UI
        }

    }
}

void Widget::updateUI(){
    QPixmap pixmap;

    //解析日期
    ui->labelCurrentDate->setText(days[0].mDate + " " + days[0].mWeek);
    //解析城市
    ui->labelCity->setText(days[0].mCity + "市");
    //解析当前温度
    ui->labelTmp->setText(days[0].mTemp + "℃");
    ui->labelTempRange->setText(days[0].mTempLow + "~" + days[0].mTempHigh + "℃");
    //解析天气类型
    ui->labelweatherType->setText(days[0].mWeatherType);
    //设置天气图标
    ui->labelWeatherIcon->setPixmap(mTypeMap[days[0].mWeatherType]);
    //感冒指数
    ui->labelGanmao->setText(days[0].mTip);
    //风向
    ui->labelFXType->setText(days[0].mFx);
    //风力
    ui->labelFXType_2->setText(days[0].mFl);
    //PM2.5
    ui->labelPM25Data->setText(days[0].mPm25);
    //湿度
    ui->labelShiduData->setText(days[0].mHu);
    //空气质量
    ui->labelairData->setText(days[0].mAirq);

    //显示六天的数据
    for(int i = 0;i < 6;i++){
        mWeekList[i]->setText(days[i].mWeek);
        //特殊设置这三天
        mWeekList[0]->setText("今天");
        mWeekList[1]->setText("明天");
        mWeekList[2]->setText("后天");

        //设置日期
        QStringList dayList = days[i].mDate.split("-");
        mDateList[i]->setText(dayList[1] + "-" + dayList[2]);

        //设置图标
        //解决没有图片的问题(防止可能出现,"某某天气"转"某某天气"这种情况,导致没有图标的情况)
        //这个函数返回子字符串在原字符串中首次出现的位置索引
        int index = days[i].mWeatherType.indexOf("转");
        if(index != -1){//出现了"转"的情况,只要左边的天气
            //从QMap里面找
            pixmap = mTypeMap[days[i].mWeatherType.left(index)];//截取了转之前的天气
        }else {
            pixmap = mTypeMap[days[i].mWeatherType];
        }
        //设置图
        pixmap = pixmap.scaled(mIconList[i]->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation);
        mIconList[i]->setPixmap(pixmap);
        //设置天气类型(这个不需要管"转")
        mWeaTypeList[i]->setText(days[i].mWeatherType);

        //设置空气质量
        QString airQ = days[i].mAirq;
        mAirqList[i]->setText(airQ);
        //设置styleSheet
        if(airQ == "优"){
            mAirqList[i]->setStyleSheet("color: rgb(230, 230, 230);\
                                        background-color: rgb(150, 213, 32);\
                                        border-radius: 7px;");
        }else if(airQ == "良"){
            mAirqList[i]->setStyleSheet("color: rgb(230, 230, 230);\
                                        background-color: rgb(208, 107, 39);\
                                        border-radius: 7px;");
        }else if(airQ == "轻度污染"){
            mAirqList[i]->setStyleSheet("color: rgb(230, 230, 230);\
                                        background-color: rgb(255, 120, 120);\
                                        border-radius: 7px;");
        }else if(airQ == "中度污染"){
            mAirqList[i]->setStyleSheet("color: rgb(230, 230, 230);\
                                        background-color: rgb(255, 17, 17);\
                                        border-radius: 7px;");
        }else if(airQ == "重度污染"){
            mAirqList[i]->setStyleSheet("color: rgb(230, 230, 230);\
                                        background-color: rgb(153, 0, 0);\
                                        border-radius: 7px;");
        }



        //设置风向和风力
        mFxList[i]->setText(days[i].mFx);
        //风力
        index = days[i].mFl.indexOf("转");
        if(index != -1){//出现了"转"的情况,只要左边的天气
            mFlList[i]->setText(days[i].mFl.left(index));
        }else {
            mFlList[i]->setText(days[i].mFl);
        }
    }
    update();
}
void Widget::readHttpReply(QNetworkReply *reply){
    //处理服务器返回的数据,数据都在这里QNetworkReply *reply
    //这个函数用于获取网络响应中的元数据信息,这些信息不是HTTP响应主体内容,而是关于请求/响应的附加数据。(比如状态码)
    int resCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug() << "resCode:" << resCode;
    if(resCode == 200 && reply->error() == QNetworkReply::NoError){//没有错误
        //qDebug() << "resCode:" << resCode;
        //获取数据(数据的形式是json,需要解析)
        QByteArray data = reply->readAll();
        parseWeatherJsonDataNew(data);//解析数据
       // qDebug() << QString::fromUtf8(data);
    }else {
         QMessageBox msgBox;
         msgBox.setText("网络请求失败");
         msgBox.setWindowTitle("错误");
         msgBox.setStandardButtons(QMessageBox::Ok);
         msgBox.setStyleSheet("QPushButton {color:red}");
         int ret = msgBox.exec();
    }
}

//需要画图的话需要重写事件过滤器

void Widget::drawTempLineHigh(){
    QPainter painter(ui->widget0404);//在ui->widget0404这里画图
    //设置属性
    painter.setPen(QColor(Qt::yellow));
    painter.setBrush(QBrush(QColor(Qt::yellow)));
    painter.setRenderHint(QPainter::Antialiasing,true);

    //临时变量
    int ave;//记录平均气温
    int sum = 0;//记录总的气温
    int offSet;//偏移量,记录平均气温和最高气温的偏移量
    int middle = ui->widget0404->height() / 2;//中间值,基于中间值来画点

    //获取sum
    for(int i = 0;i < 6;i++){
        sum += days[i].mTempHigh.toInt();
    }
    //获取平均气温
    ave = sum / 6;

    //定义六个点
    QPoint point[6];
    for(int i = 0;i < 6;i++){
        //设置x坐标
        point[i].setX(mAirqList[i]->x() + mAirqList[i]->width() / 2);
        //设置y坐标
        offSet = (days[i].mTempHigh.toInt() - ave) * 1.5;//获取偏移量
        point[i].setY(middle - offSet);//反应到ui->widget0404上面

        //画点
        painter.drawEllipse(QPoint(point[i]),3,3);
        //画出当天温度
        painter.drawText(point[i].x() - 15,point[i].y() - 10,days[i].mTempHigh + "°");

    }
    //画线(将六个点连接起来)
    for(int i = 0;i < 5;i++){
        painter.drawLine(point[i],point[i + 1]);
    }

}

void Widget::drawTempLineLow(){
    QPainter painter(ui->widget0405);//在ui->widget0405这里画图
    //设置属性QColor(70, 192, 203)
    painter.setPen(QColor(70,192,192));
    painter.setBrush(QBrush(QColor(70,192,192)));
    painter.setRenderHint(QPainter::Antialiasing,true);

    //临时变量
    int ave;//记录平均气温
    int sum = 0;//记录总的气温
    int offSet;//偏移量,记录平均气温和最高气温的偏移量
    int middle = ui->widget0405->height() / 2;//中间值

    //获取sum
    for(int i = 0;i < 6;i++){
        sum += days[i].mTempLow.toInt();
    }
    //获取平均气温
    ave = sum / 6;

    //定义六个点
    QPoint point[6];
    for(int i = 0;i < 6;i++){
        //设置x坐标
        point[i].setX(mAirqList[i]->x() + mAirqList[i]->width() / 2);
        //设置y坐标
        offSet = (days[i].mTempLow.toInt() - ave) * 1.5;//获取偏移量
        point[i].setY(middle - offSet);//反应到ui->widget0404上面

        //画点
        painter.drawEllipse(QPoint(point[i]),3,3);
        painter.drawText(point[i].x() - 15,point[i].y() - 10,days[i].mTempLow + "°");

    }
    //画线(将六个点连接起来)
    for(int i = 0;i < 5;i++){
        painter.drawLine(point[i],point[i + 1]);
    }
}
Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    //获取lineEditCity上面的数据
    QString cityNameFromuser = ui->lineEditCity->text();
    //从json文件里面找到对应城市ID
    QString citycode = c_code.getCityCodeFromName(cityNameFromuser);
    qDebug() << citycode;
    if(citycode != NULL){
        //重新拼接URL
        urlStr += "&cityid=" + citycode;
        //重新发起get请求
        reply = manager->get(QNetworkRequest(QUrl(urlStr)));
    }else {
        QMessageBox msgBox;
        msgBox.setText("请输入正确的城市名");
        msgBox.setWindowTitle("错误");
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setStyleSheet("QPushButton {color:red}");
        int ret = msgBox.exec();
    }
}

//回车响应
void Widget::on_lineEditCity_returnPressed()
{
    on_pushButton_clicked();
}

3.2 在widget.h

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include "citycodeutil.h"
#include "days.h"

#include <QLabel>
#include <QMenu>
#include <QMouseEvent>
#include <QWidget>

#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    bool eventFilter(QObject* object,QEvent* event) override;

public slots:
    void readHttpReply(QNetworkReply *reply);

private slots:
    void on_pushButton_clicked();

    void on_lineEditCity_returnPressed();

private:
    Ui::Widget *ui;
    QMenu* menuQuit;
    QPoint moffset;//这是偏移值(也就是那个差值)

    days days[7];

    QNetworkAccessManager* manager;

    QString urlStr;

    QNetworkReply* reply;

    void parseWeatherJsonDataNew(QByteArray rawData);
    void updateUI();

    //存放天气的图标
    QMap<QString,QString> mTypeMap;

    QList<QLabel *> mDateList;
    QList<QLabel *> mWeekList;
    QList<QLabel *> mIconList;
    QList<QLabel *> mWeaTypeList;
    QList<QLabel *> mAirqList;
    QList<QLabel *> mFxList;
    QList<QLabel *> mFlList;

    void drawTempLineHigh();//画最高温曲线
    void drawTempLineLow();//画最低温曲线

    citycodeutil c_code;
};
#endif // WIDGET_H

3.3 在citycodeutils.cpp

cpp 复制代码
#include "citycodeutil.h"

#include <QFile>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonArray>
citycodeutil::citycodeutil()
{

}

QString citycodeutil::getCityCodeFromName(QString cityName)
{
    //先进行判空
    if(cityMap.isEmpty()){
        //如果为空先进行初始化
        initCityMap();

    }
     //查找,根据传进来的cityName
    QMap<QString,QString>::iterator it = cityMap.find(cityName);




    if(it == cityMap.end()){//判断是否查找失败
        it = cityMap.find(cityName + "市");
        if(it == cityMap.end()){//判断是否查找失败
            it = cityMap.find(cityName + "县");
        }
        if(it == cityMap.end()){//判断是否查找失败
            it = cityMap.find(cityName + "区");
        }
        if(it == cityMap.end()){//判断是否查找失败
            return "";
        }

    }
    return it.value();//找到了
}

void citycodeutil::initCityMap()
{
    //先打开json文件
    QFile file(":/citycode.json");
    if(!file.open(QIODevice::ReadOnly))return;

    //读取文件
    QByteArray rawData = file.readAll();
    //关闭文件
    file.close();
    qDebug() << rawData;

    //处理读取出来的数据
    //转换为json
    QJsonDocument jsonObj = QJsonDocument::fromJson(rawData);

    if(!jsonObj.isNull() && jsonObj.isArray()){
        //转换为Array
        QJsonArray citys = jsonObj.array();
        //遍历citys
        for(QJsonValue val : citys){
            //并且只要city_name和city_code
            QString cityname = val["city_name"].toString();
            QString citycode = val["city_code"].toString();

            //存到QMap里面
            //这里的键值对的值为cityCode
            cityMap.insert(cityname,citycode);
        }
    }
}

3.4 在citycodeutils.h

cpp 复制代码
#ifndef CITYCODEUTIL_H
#define CITYCODEUTIL_H

#include <QMap>
#include <QString>



class citycodeutil
{
public:
    citycodeutil();
     //初始化为空,存放json文件的数据,不用每次都打开,如果每次输入一个城市
    QMap<QString,QString> cityMap = {};

    QString getCityCodeFromName(QString cityName);
    void initCityMap();
};

#endif // CITYCODEUTIL_H

3.5 在days.h(.cpp是空文件)

cpp 复制代码
#ifndef DAYS_H
#define DAYS_H

#include <QString>

class days
{
public:
    days();

    QString mDate;
    QString mWeek;
    QString mCity;
    QString mTemp;
    QString mWeatherType;
    QString mTempLow;
    QString mTempHigh;

    QString mTip;
    QString mFx;
    QString mFl;
    QString mPm25;
    QString mHu;
    QString mAirq;

};

#endif // DAYS_H

4. UI

相关推荐
Larry_Yanan4 小时前
Qt多进程(二)QProcess+stdio
开发语言·qt
码农葫芦侠4 小时前
Qt 跨线程内存管理陷阱:QSharedPointer、deleteLater() 与 QPointer 的致命组合
开发语言·数据库·qt
CC.GG5 小时前
【Qt】信号和槽
开发语言·数据库·qt
水煎包V:YEDIYYDS8888 小时前
QT QML 实现的旋钮按钮,类似收音机音量旋钮,可指示方向和角度
qt·qml·旋钮组件
龚建波8 小时前
Qt程序设计:QPromise/QFuture多线程任务管理
qt·qfuturewatcher·qpromise·qfuture
追烽少年x9 小时前
Qt面试题合集(三)
qt
FirstFrost --sy9 小时前
Qt控件美化:LineEdit与CheckBox实战
开发语言·qt
Larry_Yanan17 小时前
Qt多进程(一)进程间通信概括
开发语言·c++·qt·学习