Qt——天气预报项目

一.ui界面的设计流程

1.窗口1:使用水平布局,内包含俩个QLabel类和一个QLineEdit类

这里可以设置LineEdit中的提示文字 

2.窗口2:使用栅格布局,这个天气图标组件的大小需限制一下

 3.窗口3:里面包含一个子窗口,设置子窗口背景样式为橘色

子窗口中的组件先垂直布局,后水平布局。最后整体再来一个栅格布局

4.窗口4:里面包含6个子窗口。子窗口0401、0402、0406都需要进行栅格布局

子窗口0401和0406中的组件是由俩个QLabel类拼接在一起的。

 

5.最后给4个窗口整体进行垂直布局即可

二.功能实现逻辑

2.1 如何实现单击右键时,弹出菜单,供用户选择是否要退出的功能?

解决方法:重写鼠标点击事件,以及绑定信号与槽。 当用户单击右键时候,在点击位置处显示出该菜单。当用户选择菜单后,会发出triggered信号,调用槽函数即可。

构造函数中先初始化菜单类

myMenu = new QMenu(this);                                         //创建一个菜单加"Quit"和"not Quit"动作
QAction *QuitAction = new QAction("Quit", myMenu);
QAction *notQuitAction = new QAction("Not Quit", myMenu);
myMenu->addAction(QuitAction);                                    //往菜单中添加组件 
myMenu->addAction(notQuitAction);connect(myMenu, &QMenu::triggered, this, [=](QAction *action){    //当用户点击这些动作时,会发出triggered信号if (action->text() == "Quit") {this->close();} else if (action->text() == "Not Quit") {return;}
});

重写鼠标点击事件

void Widget::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::RightButton){                               //当检测到鼠标右键按下时,在当前点击位置弹出菜单myMenu->exec(QCursor::pos());}QWidget::mousePressEvent(event);
}

2.2 如何实现用户鼠标左键拖拽窗口移动功能?

解决方法:重写鼠标点击事件和鼠标移动事件。

void Widget::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::RightButton){                               //当检测到鼠标右键按下时,在当前点击位置弹出菜单myMenu->exec(QCursor::pos());}if(event->button() == Qt::LeftButton){mOffset = event->globalPos() - this->pos();                       //偏移值等于鼠标当前位置减去窗口当前的位置}QWidget::mousePressEvent(event);
}void Widget::mouseMoveEvent(QMouseEvent *event)
{//鼠标当前位置减去偏移值等于新的窗口的左顶点坐标this->move(event->globalPos() - mOffset);
}

2.3 如何获取天气数据?

解决方法:QT调用HTTP请求相应的网站会返回 JSON 数据,解析该JSON数据中包含了天气数据

步骤1:首先打开下面网站,进行用户注册,随后会生成id和密码(后续http请求的网址中要包含的)

实时天气预报api 24小时天气预报接口 实时气象预警 空气质量预报

 或者通过别的api进行访问天气情况,使用时候需更换后面的city_id的值即可

http://t.weather.itboy.net/api/weather/city/101030100

步骤2:网站主页有相应的网址访问示例,如果想访问特定城市,需在链接后面拼接城市id等数据

步骤3:复制所有json内容,通过以下网站可以解析这些数据,选择你所需要字段名

JSON在线解析及格式化验证 - JSON.cn

步骤四:除此之外,你还需要有存储着城市姓名和城市id的文档,以便于你后期搜索城市天气时候,可以根据该文档获取到城市的city_id,然后拼接网址进行HTTP请求

通过以下代码可以实现查询城市id时,不用每次都重新打开json文档,而是把json文档中的city_name和 city_id键值对存入QMap中,当需要时直接在QMap中进行查找并返回相应的city_id

#include <QFile>
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include "citycodeutils.h"CityCodeUtils::CityCodeUtils() {}// 根据用户输入的城市名在QMap中检索,返回相应的code_id
QString CityCodeUtils::getCityCodeFromName(QString cityName)
{// 如果QMap为空,则调用初始化函数,解析json数据提取城市名字和id存入QMap中if(cityMap.isEmpty()){initCityMap();}QString city_name2 = QString("%1市").arg(cityName); //假设用户输入的不带市QString city_name3 = QString("%1县").arg(cityName); //假设用户输入的不带县QString city_name4 = cityName;                      //假设用户输入的带市,但是我们不需要市if (city_name4.contains("市")) {city_name4.remove("市");}QString city_name5 = cityName;                      //假设用户输入的带县,但是我们不需要县if (city_name5.contains("县")) {city_name5.remove("县");}QMap<QString, QString>::const_iterator it = cityMap.constBegin();  //迭代器指向QMap的起始while (it != cityMap.constEnd()) {                                 //利用迭代器遍历QMapif(it.key() == cityName || it.key() == city_name2 || it.key() == city_name3 || it.key() == city_name4 ||it.key() == city_name5){return it.value();                                         //返回对应的code_idbreak;                                                     //返回后结束当前循环}++it;}return 000000;                                                     //若没有找到匹配的,则返000000,代表错误代码
}// 负责解析本地的json数据,提取出城市名字和code_id存入QMap中
void CityCodeUtils::initCityMap()
{QFile file(":/aaa.json");file.open(QIODevice::ReadOnly);QString data = QString::fromUtf8(file.readAll());file.close();QJsonDocument jsonDoc = QJsonDocument::fromJson(data.toUtf8());    //将读取的json字符串转化为jsonDocument文档// 准备一个 QMap 来存储解析的数据QMap<QString, QString> dataMap;// 如果jsonDocument文档是一个数组if (!jsonDoc.isNull() && jsonDoc.isArray()) {QJsonArray jsonArray = jsonDoc.array();                        //将json文档转化为一个jsonArray数组for (const QJsonValue &value : jsonArray) {                    //遍历数组中的每个对象if (value.isObject()) {QJsonObject jsonObj = value.toObject();                //将数组中的对象赋值给json对象,然后根据键值对提取json对象中的内容QString city_name = jsonObj["city_name"].toString();QString city_code = jsonObj["city_code"].toString();cityMap.insert(city_name,city_code);                   //向QMap中插入键值对}}}
}

2.4 如何实现将网站返回的json天气数据缓存下来

解决方法:先检查是否有本地缓存的json天气数据,如果有的话,则进一步判断该文件是否过期,如果没过期的话,就解析旧的json天气数据。否则进行http请求,将返回的json天气数据保存下来,然后进行解析该数据,往控件上显示。否则,旧进行http请求。

并且当用户搜索相应的城市天气时,我先不进行http请求,我检查一下这个新的网址和旧的网址是不是一样的,如果是一样的,那就重复上述步骤,查看本地是否有缓存的json天气数据,以及该数据是否过期。如果文件不存在或已过期,或者是网址与旧的网址不同,那么就进行http请求。

/*解析json数据*/
void Widget::praseJsonData(QString jsonString) {// 将JSON字符串转换为QJsonDocument文档QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());// 检查JSON文档是否有效if (jsonDoc.isNull() || !jsonDoc.isObject()) {qDebug() << "Invalid JSON data!";return;}// 把JSON文档转化为json对象QJsonObject jsonObj = jsonDoc.object();// 城市信息解析(**城市名称,省会名称**)if (jsonObj.contains("cityInfo") && jsonObj["cityInfo"].isObject()) {QJsonObject cityInfo = jsonObj["cityInfo"].toObject();QString city = cityInfo.value("city").toString("未知城市");QString parent = cityInfo.value("parent").toString("未知省份");QString updateTime = cityInfo.value("updateTime").toString("未知时间");ui->label_city->setText(QString("%1, %2").arg(parent).arg(city)); // *设置城市名称和省份}// 天气数据解析if (jsonObj.contains("data") && jsonObj["data"].isObject()) {QJsonObject data = jsonObj["data"].toObject();ui->label_WeatherNum->setText(data.value("wendu").toString("N/A") + "℃");      // *设置当天温度ui->label_WetNum->setText(data.value("shidu").toString("N/A"));                 // *设置当天湿度ui->label_AirNum->setText(data.value("quality").toString("N/A"));               // *设置当天空气质量qint16 Pm25 = data.value("pm25").toInt(-1);                                     // 获取当天的pm2.5ui->label_PmNum->setText(QString::number(Pm25));                                // *设置当天PM2.5ui->label_GanMao->setText(data.value("ganmao").toString("N/A"));                // *设置提示信息// 解析昨天的天气if (data.contains("yesterday") && data["yesterday"].isObject()) {QJsonObject yestObj = data["yesterday"].toObject();QString high = extractTemperature(yestObj.value("high").toString());        // 获取并提取昨天的最高温度dayHighTem[0] = high;QString low = extractTemperature(yestObj.value("low").toString());          // 获取并提取昨天的最低温度dayLowTem[0] = low;QString type = yestObj.value("type").toString("未知");                       // 获取昨天的天气状况QString date = yestObj.value("ymd").toString("未知日期");                     // 获取昨天的日期qint16 aqi = yestObj.value("aqi").toInt(-1);                                 // 获取昨天的空气质量指数ui->label_01->setStyleSheet(aqi <= 50 ? "background-color: rgb(85, 170, 0);" :(aqi <= 100 ? "background-color: rgb(255, 146, 21);" :"background-color: rgb(255, 0, 0);"));QStringList parts = date.split("-");QString lastDate = parts.size() == 3 ? QString("%1-%2").arg(parts[1]).arg(parts[2]) : "未知日期";ui->label_date1->setText(lastDate);                                          // *设置昨天的日期ui->label_sweather01->setText(type);                                         // *设置昨天的天气auto it = mTypeMap.find(type);                                               // *设置昨天的天气图片if (it != mTypeMap.end()) {QString IconPath = it.value();QPixmap pixmap(IconPath);ui->label_sweather1->setPixmap(pixmap);} else {qDebug() << "Weather type not found in mTypeMap:" << type;}ui->label_01->setText(aqi <= 50 ? "优" : (aqi <= 100 ? "良" : "差"));          // *设置昨天的空气质量ui->label_windDir1->setText(yestObj.value("fx").toString("未知风向"));         // *设置昨天的风向ui->label_windDir01->setText(yestObj.value("fl").toString("未知风级"));        // *设置昨天的风级}// 解析未来天气预报if (data.contains("forecast") && data["forecast"].isArray()) {QJsonArray forecastArray = data["forecast"].toArray();int i = 1;for (const QJsonValue &value : forecastArray) {if (value.isObject()) {QJsonObject forecast = value.toObject();QString high = extractTemperature(forecast.value("high").toString());   //获取并提取出最高温度dayHighTem[i] = high;QString low = extractTemperature(forecast.value("low").toString());     //获取并提取出最低温度dayLowTem[i] = low;QString type = forecast.value("type").toString("未知");                  //获取天气情况QString date = forecast.value("ymd").toString("未知日期");               //获取日期QString fx = forecast.value("fx").toString("未知风向");                  //获取风向QString fl = forecast.value("fl").toString("未知风级");                  //获取风级qint16 aqi = forecast.value("aqi").toInt(-1);                          //获取空气指数QStringList parts = date.split("-");QString lastDate = parts.size() == 3 ? QString("%1-%2").arg(parts[1]).arg(parts[2]) : "未知日期";if(i == 1){ui->label_WeatherStaute->setText(type);                            //设置当天的天气情况ui->label_FxTitle->setText(fx);                                    //设置当天的风向ui->label_FxNum->setText(fl);                                      //设置当天的风级}QLabel *label_day = findChild<QLabel *>(QString("label_day%1").arg(i + 1));QLabel *label_date = findChild<QLabel *>(QString("label_date%1").arg(i + 1));QLabel *label_sweather = findChild<QLabel *>(QString("label_sweather0%1").arg(i + 1));QLabel *label_windDir = findChild<QLabel *>(QString("label_windDir%1").arg(i + 1));QLabel *label_windDir0 = findChild<QLabel *>(QString("label_windDir0%1").arg(i + 1));QLabel *label_airQuality = findChild<QLabel *>(QString("label_0%1").arg(i + 1));if (label_day && label_date && label_sweather && label_windDir && label_windDir0 && label_airQuality) {label_day->setText(i == 1 ? "今天" : forecast.value("week").toString("未知"));     //*设置星期几label_date->setText(lastDate);                                                    //*设置日期label_sweather->setText(type);                                                    //*设置天气情况label_windDir->setText(fx);                                                       //*设置风向label_windDir0->setText(fl);                                                      //*设置风级QString airStatus = (aqi <= 50) ? "优" : ((aqi <= 100) ? "良" : "差");label_airQuality->setText(airStatus);                                             //*设置空气质量label_airQuality->setStyleSheet(aqi <= 50 ? "background-color: rgb(85, 170, 0);" :(aqi <= 100 ? "background-color: rgb(255, 146, 21);" :"background-color: rgb(255, 0, 0);"));auto it = mTypeMap.find(type);if (it != mTypeMap.end()) {QString IconPath = it.value();QPixmap pixmap(IconPath);if(i == 1){                                                                   //*设置当天的天气质量图片ui->label_WeatherImage->setPixmap(pixmap);}QLabel *label_weatherIcon = findChild<QLabel *>(QString("label_sweather%1").arg(i + 1));if (label_weatherIcon) {label_weatherIcon->setPixmap(pixmap);                                    //*设置天气质量图片}}} else {qDebug() << "One or more labels not found for day" << i;}if(i < 5){i++;}}}}}update(); // 更新界面}//获取http请求的数据并将返回数据保存到本地文档中
void Widget::readHttpRequest()
{int resCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();    // 获取返回码,正确获取为200,错误时为404qDebug() << "resCode:" << resCode;if(resCode == 200 && reply->error() == QNetworkReply::NoError){QString response = QString::fromUtf8(reply->readAll());                           //获取返回信息QFile file("C:/Users/mi/Desktop/Qt_Project/Weather-forecast/json_data");if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){qDebug() << "文件打开失败";}file.write(response.toLocal8Bit());                                               //将返回的json数据写入文件中file.close();praseJsonData(response);                                                          //解析json数据}else{qDebug() << "Error:" << reply->errorString();                                     //获取错误信息QMessageBox::warning(this,"错误","网络请求失败",QMessageBox::Ok);}
}//检查本地json文件是否存在,以及是否该重新访问
void Widget::checkAndLoadWeatherData()
{QString cacheFilePath = "C:/Users/mi/Desktop/Qt_Project/Weather-forecast/json_data"; // 缓存文件路径QFileInfo cacheFileInfo(cacheFilePath);if (cacheFileInfo.exists()) {// 文件存在,检查是否过期QDateTime lastModified = cacheFileInfo.lastModified();QDateTime currentTime = QDateTime::currentDateTime();qint64 elapsedSecs = lastModified.secsTo(currentTime);qDebug() << "缓存存在,距离上次修改的时间:" << elapsedSecs << "秒";if (elapsedSecs <= 3600) { // 如果文件修改时间在1小时内// 解析本地缓存文件QFile cacheFile(cacheFilePath);if (cacheFile.open(QIODevice::ReadOnly)) {QString jsonData = QString::fromLocal8Bit(cacheFile.readAll());cacheFile.close();qDebug() << "使用本地缓存数据";praseJsonData(jsonData);return; // 使用缓存数据后返回}}}// 如果缓存不存在或已过期,则发送 HTTP 请求qDebug() << "缓存无效,发送HTTP请求获取数据";QUrl url(website);QNetworkRequest request(url);reply = manager->get(request);
}//根据用户输入的城市名进行查询天气数据
void Widget::weatherSearch()
{QString ser_city_name = ui->lineEdit_searchData->text();                               //获取用户输入的城市名QString cityCode = citycodeUtils->getCityCodeFromName(ser_city_name);                  //获取返回的城市idif(cityCode == 000000){                                                                //返回错误代码,则不进行http请求QMessageBox msgBox;msgBox.setText("未检索到城市.");msgBox.exec();}else{website = QString("http://t.weather.itboy.net/api/weather/city/%1").arg(cityCode); //拼接要访问的网址if(website == lastwebsite){                                                        //如果此次访问的和上次访问的一样,则不进行http请求checkAndLoadWeatherData();}else{lastwebsite = website;QUrl url(website);QNetworkRequest request(url);reply = manager->get(request);                                                 //进行http请求}}
}

2.5 如何在控件上绘制6天的高低温折线图?

解决方法:重写事件过滤函数,为控件widget_0404和widget_0405安装事件过滤器

检测到绘制信号时候,调用函数进行绘制高低温曲线

/*绘制低温曲线*/
void Widget::drawTempLineHigh()
{QPainter painter(ui->widget_0404);painter.setRenderHint(QPainter::Antialiasing, true);              //启用抗锯齿int sum = 0;int ave;int offset = 0;int middle = ui->widget_0404->height() / 2;QFont font("Arial", 10);painter.setFont(font);for (int i = 0; i < 6; i++) {sum += dayHighTem[i].toInt();}ave = sum / 6;QPoint points[6];for (int i = 0; i < 6; i++) {points[i].setX(lab[i]->x() + lab[i]->width() / 2);             //当前点的横坐标位置与其头顶上方的空气质量组件有关offset = dayHighTem[i].toInt() - ave;                          //偏移值等于当天温度-平均值,可乘以适当倍数以增加曲率points[i].setY(middle - offset);                               //因为画笔直接与当前窗口关联了,所以纵坐标等于当前窗口高度-偏移值painter.setPen(Qt::yellow);painter.setBrush(Qt::yellow);painter.drawEllipse(points[i], 2, 2);                          //绘制圆点QString temperatureText = QString("%1℃").arg(dayHighTem[i]);QPoint textPosition(points[i].x() - 7, points[i].y() + 15);    //调整文字位置painter.setPen(QColor(Qt::white));painter.drawText(textPosition, temperatureText);               //在点的下方绘制温度值}painter.setPen(Qt::yellow);for (int i = 0; i < 5; i++) {painter.drawLine(points[i], points[i + 1]);                    //绘制5条温度西线}
}/*绘制高温曲线*/
void Widget::drawTempLineLow()
{QPainter painter(ui->widget_0405);painter.setRenderHint(QPainter::Antialiasing, true);int sum = 0;int ave;int offset = 0;int middle = ui->widget_0405->height() / 2;QFont font("Arial", 10);painter.setFont(font);for (int i = 0; i < 6; i++) {sum += dayLowTem[i].toInt();}ave = sum / 6;QPoint points[6];for (int i = 0; i < 6; i++) {points[i].setX(lab[i]->x() + lab[i]->width() / 2);offset = dayLowTem[i].toInt() - ave;points[i].setY(middle - offset);painter.setPen(QColor(35, 255, 255));painter.setBrush(QColor(35, 255, 255));painter.drawEllipse(points[i], 2, 2);QString temperatureText = QString("%1℃").arg(dayLowTem[i]);QPoint textPosition(points[i].x() - 7, points[i].y() + 15);painter.setPen(QColor(Qt::white));painter.drawText(textPosition, temperatureText);}painter.setPen(QColor(35, 255, 255));for (int i = 0; i < 5; i++) {painter.drawLine(points[i], points[i + 1]);}
}/*事件过滤函数*/
bool Widget::eventFilter(QObject *watched, QEvent *event)
{if(watched == ui->widget_0404 && event->type() == QEvent::Paint){drawTempLineHigh();return true;}if(watched == ui->widget_0405 && event->type() == QEvent::Paint){drawTempLineLow();return true;}return QWidget::eventFilter(watched,event);
}

三.HTTP通信知识补充

3.1 QT实现HTTP通信

HTTP(超文本传输协议)是用于分布式、协作式和超媒体信息系统的应用层协议,是万维网(WWW)的数据通信的基础。了解HTTP的基本概念对于理解现代网络通信至关重要。以下是HTTP的一些核心概念:

请求和响应:HTTP是一个基于请求-响应模式的协议。客户端(通常是Web浏览器)向服务器发送一个HTTP请求,然后服务器返回一个HTTP响应。请求包含请求的资源(如网页),而响应包含请求的资源的内容。
HTTP方法:
  • HTTP定义了一系列的方法来表明对资源的不同操作,最常用的包括:
    • GET:用于请求资源。
    • POST:用于提交数据给服务器(例如,表单数据)。
    • PUT:用于上传文件或内容。
    • DELETE:用于请求删除资源。
    • HEAD:用于获取资源的元信息,而不是资源本身。
状态码:
  • 服务器对请求的响应中包含一个状态码,它表示请求的成功或失败,以及失败的原因。常见的状态码包括:
    • 200 OK:请求成功。
    • 404 Not Found:请求的资源未找到。
    • 500 Internal Server Error:服务器内部错误。

Qt中的HTTP编程涉及到使用Qt中的网络模块来进行HTTP请求和处理HTTP响应。

QNetworkAccessManager,QNetworkRequest,QNetworkReply

以下程序展示了如何使用Qt发送一个简单的HTTP请求并处理响应

//包含在头文件中
QNetworkAccessManager *manager;
QNetworkReply *reply;//包含在构造函数中
manager = new QNetworkAccessManager(this);
QNetworkRequest request(QUrl("http://t.weather.itboy.net/api/weather/city/101010100"));
reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, &Widget::readHttpRequest);
//或者绑定完成信号与manager对象更好
//connect(manager,&QNetworkAccessManager::finished, this, &Widget::readHttpRequest);//自定义函数
void Widget::readHttpRequest()
{int resCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); // 获取返回码,正确获取为200,错误时为404qDebug() << "resCode:" << resCode;if(resCode == 200 && reply->error() == QNetworkReply::NoError){QString response = QString::fromUtf8(reply->readAll());                           //获取返回信息qDebug() << "response:" << response;}else{qDebug() << "Error:" << reply->errorString();                                 //获取错误信息QMessageBox::warning(this,"错误","网络请求失败",QMessageBox::Ok);}
}

3.2 Qt生成JSON数据

JSON(JavaScript ObjectNotation)是一种轻量级的数据交换格式。它易于人阅读和编写,同时也易于机器解析和生成。JSON是基于JavaScript的一个子集,尽管它是独立于语言的,且有多种语言支持。JSON常用于网络应用程序中的数据传输,尤其是在Web应用程序中与后端服务器通信。

在Qt中生成JSON数据并将其保存到文件的一个基本示例涉及使用QJsonDocument、QJsonObject和QJsonArray类。以下是创建一个简单JSON对象并将其保存到文件的示例代码。

#include <QJsonDocument>
#include <QJsonObject>
#include <QFile>
#include <QDebug>
#include <QJsonArray>QJsonObject rootObj;                  //创建一个json对象,键值对
rootObj["cityid"] = "1010100";
rootObj["date"] = "2024-11-13";
rootObj["weather"] = "雨夹雪";QJsonArray jsonArr;                   //创建一个JSON数组
jsonArr.append("C++");
jsonArr.append("Python");             
rootObj["languages"]=jsonArr;         //将数组添加到JSON对象QJsonDocument JsonDoc(rootObj);       //将json对象转化为json文档
QByteArray json = JsonDoc.toJson();   //将json文档转化为字符串QFile file("C:/Users/mi/Desktop/Qt_Project/Qt_JsonData/jsonData");
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){qDebug() << "文件打开失败";
}
file.write(json);                     //写入文件中
file.close();

3.3 Qt解析JSON数据

在Qt中解析JSON数据通常涉及到使用QJsonDocument、QJsonObject和QJsonArray类。这些类提供了处理JSON数据的必要工具,使您能够从JSON字符串中提取信息、遍历JSON对象或数组,并访问具体的数据项。

以下是如何在Qt中解析这个JSON字符串的步骤:

示例1:json文档中只包含1个对象

// 1.使用了原始字符串字面量来定义JSON字符串,这样可以避免转义特殊字符
QString jsonString = R"({"name": "John Doe","age": 30,"email": "john.doe@example.com","skills": ["C++", "Python", "JavaScript"]})";// 2.将JSON字符串转换为QJsonDocument文档
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());// 3.检查JSON文档是否包含一个对象
if (!jsonDoc.isNull() && jsonDoc.isObject()) {// 3.1获取JSON对象并访问其键值QJsonObject jsonObj = jsonDoc.object();QString name = jsonObj["name"].toString();int age = jsonObj["age"].toInt();QString email = jsonObj["email"].toString();qDebug() << "Name:" << name;qDebug() << "Age:" << age;qDebug() << "Email:" << email;// 3.2获取JSON对象中的数组if (jsonObj.contains("skills") && jsonObj["skills"].isArray()) {QJsonArray skillsArray = jsonObj["skills"].toArray();for (const QJsonValue &value : skillsArray) {qDebug() << "Skill:" << value.toString();}}
} else {qDebug() << "Invalid JSON.";
}

示例2:json文档中包含多个对象

// 1.定义一个包含多个对象的JSON字符串
QString jsonString = R"([{"name": "小李","age": 18,"email": "xiaoli.doe@example.com","skills": ["C++", "Python", "JavaScript"]},{"name": "小美","age": 25,"email": "xiaomei.smith@example.com","skills": ["Java", "C#", "PHP"]}])";// 2.将JSON字符串转换为QJsonDocument对象
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());// 3.检查JSON文档是否包含一个数组,多个对象保存到一个数组中
if (!jsonDoc.isNull() && jsonDoc.isArray()) {QJsonArray jsonArray = jsonDoc.array();                     //3.1获取json文档中的数组for (const QJsonValue &value : jsonArray) {                 //3.2遍历数组中的每个对象if (value.isObject()) {QJsonObject jsonObj = value.toObject();             //3.3将数组中的对象赋值给json对象,然后根据键值对提取json对象中的内容QString name = jsonObj["name"].toString();int age = jsonObj["age"].toInt();QString email = jsonObj["email"].toString();qDebug() << "Name:" << name;qDebug() << "Age:" << age;qDebug() << "Email:" << email;if (jsonObj.contains("skills") && jsonObj["skills"].isArray()) {QJsonArray skillsArray = jsonObj["skills"].toArray();for (const QJsonValue &skillValue : skillsArray) {qDebug() << "Skill:" << skillValue.toString();}}}}
} else {qDebug() << "Invalid JSON or not an array.";
}

3.4 Qt解析JSON数据并存储到QMap类中

// JSON 字符串
QString jsonString = R"({"name": "John Doe","age": "30","email": "john.doe@example.com"})";// 将 JSON 字符串转换为 QJsonDocument
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());// 准备一个 QMap 来存储解析的数据
QMap<QString, QString> dataMap;// 解析 JSON 对象并填充 QMap
if (!jsonDoc.isNull() && jsonDoc.isObject()) {QJsonObject jsonObj = jsonDoc.object();for (auto key : jsonObj.keys()) {dataMap[key] = jsonObj.value(key).toString();}
} else {qDebug() << "Invalid JSON...";
}// 打印 QMap 内容
for (auto key : dataMap.keys()) {qDebug() << key << ": " << dataMap[key];
}

四.整体代码实现如下

tunnek/mimi: QT——天气预报项目 (github.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/60489.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【高阶数据结构】LRU Cache

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解什么是LRU Cache&#xff0c;并能简单的模拟实现。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! &…

jupyter notebook的 markdown相关技巧

目录 1 先选择为markdown类型 2 开关技巧 2.1 运行markdown 2.2 退出markdown显示效果 2.3 注意点&#xff1a;一定要 先选择为markdown类型 3 一些设置技巧 3.1 数学公式 3.2 制表 3.3 目录和列表 3.4 设置各种字体效果&#xff1a;加粗&#xff0c;斜体&#x…

stm32 指定变量存储地址

uint8_t array[10] attribute((at(0x20000000))) 当你使用 attribute((at(地址))) 强制将变量放置在特定地址时&#xff0c;编译器和链接器通常不会自动调整其他变量的地址以避免冲突。这意味着&#xff0c;如果指定的地址已经被其他变量占用&#xff0c;就会发生冲突。 如果…

安宝特分享 | 如何利用AR技术革新医疗实践:从远程急救到多学科协作

AR技术在国内外医院的应用 在现代医疗环境中&#xff0c;患者面临的挑战依然严峻&#xff1a;看病难、看病远、看病急。这些问题不仅影响了患者的治疗效果&#xff0c;也让医务工作者倍感压力。幸运的是&#xff0c;随着增强现实&#xff08;AR&#xff09;技术的发展&#xf…

从零开始:如何使用第三方视频美颜SDK开发实时直播美颜平台

开发一个具有实时美颜功能的直播平台&#xff0c;能够显著提高用户体验和内容质量。而利用第三方视频美颜SDK可以大大简化开发过程&#xff0c;加快产品上市速度。本篇文章&#xff0c;小编将从零开始&#xff0c;详细讲解如何使用第三方视频美颜SDK开发一个实时直播美颜平台。…

记录第一次安装laravel项目

window系统 Laravel中文文档&#xff1a;https://laravel-docs.catchadmin.com/docs/11/getting-started/installation 1.使用composer安装全局laravel composer global require laravel/installer2.安装完成后在命令行输入laravel&#xff0c;如果报错&#xff1a;laravel不是…

《Django 5 By Example》阅读笔记:p651-p678

《Django 5 By Example》学习第9天&#xff0c;p651-p678总结&#xff0c;总计28页。 一、技术总结 1.aggregate() (1)aggregate&#xff1a;ad-(“to”) gregare(“to collection into a flock(群)&#xff0c; to gather”) 因为ad 后面跟的是gregate&#xff0c;为了发…

安卓手机5G网络频繁掉4G 问题解决 手机5G网络优化方案

问题环境 在某个长期停留的位置&#xff08;例如&#xff1a;躺平&#xff09;使用手机时网络突然从5G跳到4G&#xff0c;偶尔跳来跳去导致网络体验很差&#xff0c;经过调整5G网络情况下网速及其他体验都要更好&#xff0c;基于这样的情况使用一种简单的操作&#xff0c;锁定5…

利用c语言详细介绍下希尔排序

希尔排序是针对插入排序的优化算法。它是缩少增量的算法&#xff0c;一开始增量从元素个数len/2的增量开始&#xff0c;然后缩小增量gapgap/2&#xff0c;直到gap为1&#xff0c;最终完成序列排序。 一、图文介绍 我们还是使用数组【10&#xff0c;5&#xff0c;3&#xff0c;2…

基于MATLAB的超宽带(UWB)信号的仿真和测试系统

基于MATLAB的超宽带(UWB)信号的仿真和测试系统 引言 随着无线通信技术的发展&#xff0c;超宽带&#xff08;Ultra-Wideband, UWB&#xff09;技术因其高数据传输速率、低功耗、抗多径衰落等优点而受到广泛关注。UWB技术适用于短距离高速数据传输&#xff0c;如个人区域网络、…

深度学习:GPT-1的MindSpore实践

GPT-1简介 GPT-1&#xff08;Generative Pre-trained Transformer&#xff09;是2018年由Open AI提出的一个结合预训练和微调的用于解决文本理解和文本生成任务的模型。它的基础是Transformer架构&#xff0c;具有如下创新点&#xff1a; NLP领域的迁移学习&#xff1a;通过最…

day06(单片机高级)PCB设计

目录 PCB设计 PCB设计流程 元器件符号设计 原理图设计 元器件封装设计 元器件库使用 PCB设计 目的&#xff1a;学习从画原理图到PCB设计的整个流程 PCB设计流程 元器件符号设计 元器件符号&#xff1a;这是电子元器件的图形表示&#xff0c;用于在原理图中表示特定的元器件。例…

人工智能(AI)与机器学习(ML)基础知识

目录 1. 人工智能与机器学习的核心概念 什么是人工智能&#xff08;AI&#xff09;&#xff1f; 什么是机器学习&#xff08;ML&#xff09;&#xff1f; 什么是深度学习&#xff08;DL&#xff09;&#xff1f; 2. 机器学习的三大类型 &#xff08;1&#xff09;监督式学…

Java 调用 MULTIPART_FORM_DATA 接口

以 QAnthing 上传文件&#xff08;POST&#xff09;接口为例&#xff0c;展示Java如何调用上传文件接口。 接口文档如下&#xff1a; QAnthign接口文档地址 编码 RestTemplate 版 /** * * param url 接口地址 * param filePath 文件本地路径 */ public void uploadFile(S…

Vue3-小兔鲜项目出现问题及其解决方法(未写完)

基础操作 &#xff08;1&#xff09;使用create-vue搭建Vue3项目 要保证node -v 版本在16以上 &#xff08;2&#xff09;添加pinia到vue项目 npm init vuelatest npm i pinia //导入creatPiniaimport {createPinia} from pinia//执行方法得到实例const pinia createPinia()…

【Vue】 npm install amap-js-api-loader指南

前言 项目中的地图模块突然打不开了 正文 版本太低了&#xff0c;而且Vue项目就应该正经走项目流程啊喂&#xff01; npm i amap/amap-jsapi-loader --save 官方说这样执行完&#xff0c;就这结束啦&#xff01;它结束了&#xff0c;我还没有&#xff0c;不然不可能记录这篇文…

C#桌面应用制作计算器进阶版01

基于C#桌面应用制作计算器做出了少量改动&#xff0c;其主要改动为新增加了一个label控件&#xff0c;使其每一步运算结果由label2展示出来&#xff0c;而当点击“”时&#xff0c;最终运算结果将由label1展示出来&#xff0c;此时label清空。 修改后运行效果 修改后全篇代码 …

Linux下Intel编译器oneAPI安装和链接MKL库编译

参考: https://blog.csdn.net/qq_44263574/article/details/123582481 官网下载: https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit-download.html?packagesoneapi-toolkit&oneapi-toolkit-oslinux&oneapi-linoffline 填写邮件和国家,…

文件管理 IV(文件系统)

一、文件系统结构 文件系统&#xff08;File system&#xff09;提供高效和便捷的磁盘访问&#xff0c;以便允许存储、定位、提取数据。文件系统有两个不同的设计问题&#xff1a;第一个问题是&#xff0c;定义文件系统的用户接口&#xff0c;它涉及定义文件及其属性、所允许的…

基于ToLua的C#和Lua内存共享方案保姆级教程

C#和Lua内存共享方案保姆级教程 前言 在介绍C#和Lua内存共享方案之前,先介绍下面两个点来支撑这个方案的必要性 跨语言交互很费 Lua和C#交互最早是基于反射的方式实现的,后来为了提升性能发展成Luajit+C#静态方法导出注入到lua虚拟机的方式至此Lua+Unity的性能才达到了实…