哪个网站做投票链接模板好看,成品短视频网站源码搭建免费,白沙网站建设,阿里云网站建设教程2017【C QT项目5】——基于HTTP与JSON数据流的天气预报界面设计 一、项目概述二、UI设计与stylesheet样式表三、天气预报数据接口四、JSON数据4.1 概述4.2 QT生成JSON数据4.3 QT解析JSON数据4.4 将JSON数据解析到QMap中 五、软件开发网络通信架构5.1 BS架构/CS架构5.2 HTTP基本概念… 【C QT项目5】——基于HTTP与JSON数据流的天气预报界面设计 一、项目概述二、UI设计与stylesheet样式表三、天气预报数据接口四、JSON数据4.1 概述4.2 QT生成JSON数据4.3 QT解析JSON数据4.4 将JSON数据解析到QMap中 五、软件开发网络通信架构5.1 BS架构/CS架构5.2 HTTP基本概念5.3 Qt中的HTTP编程 6. 天气预报项目整合6.1 连接请求解析JSON数据并刷新界面6.2 支持不同城市查询的实现6.3 七日温度曲线的绘制 一、项目概述
设计一个天气预报界面实现对不同城市区域的天气获取与显示其中主要涉及
stylesheet界面美化HTTP通信JSON数据解析自定义控件绘制温度多控件及其最终代码整合调试能力。
二、UI设计与stylesheet样式表
界面Layout设计 上下两部分命名规则
stylesheet样式表美化 设置边框弧度
border-radius: 4px;设置某方向边框弧度
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;设置背景颜色
background-color: rgba(60, 60, 60, 100);设置字体颜色
color: rgb(230, 230, 230);设置字体大小
font: 45pt;设置按钮的三态
QPushButton#button1{background-color: rgba(220, 250, 220, 255);border:10px solid white;border-radius:32px;font-size:60px;
}
QPushButton#button1:hover{ background-color: rgba(255, 255, 0, 255);border:10px solid white;border-radius:32px;color:#FF00FE;font-size:60px;
}
QPushButton#button1:pressed{background-color: rgba(255, 255, 0, 255);border:10px solid white;border-radius:32px;color: #FF00FE;font-size:60px;
} 为按钮/标签添加背景图片
父控件影响 父控件指定某类控件的样式子控件都要遵守此样式进行显示除非子控件内部有做相关修改
QLabel
{background-color: rgba(0, 200, 200, 200);border-radius: 4px;
}三、天气预报数据接口
以下API网站返回的数据实际是JSON格式的数据可以利用 该网站对数据进行可视化解析展示JSON在线解析及格式化验证 - JSON
第一种
http://t.weather.itboy.net/api/weather/city/101010100
数据返回
第二种 获取IP地址所属地的一日天气状况
http://v1.yiketianqi.com/api?unescape1versionv61appid89361488appsecretK6tTmCT0
获取特定城市的天气状况
http://v1.yiketianqi.com/api?unescape1versionv61appid89361488appsecretK6tTmCT0cityid实际城市的ID值
获取特定城市的未来7日天气状况
http://v1.yiketianqi.com/api?unescape1versionv9appid89361488appsecretK6tTmCT0cityid实际城市的ID值
例如http://v1.yiketianqi.com/api?unescape1versionv9appid89361488appsecretK6tTmCT0cityid101040100
返回一日的天气数据 返回七日天气数据
四、JSON数据
4.1 概述 JSONJavaScript Object Notation是一种轻量级的数据交换格式以键值对的形式存在。它易于人阅读和编写同时也易于机器解析和生成。SON常用于网络应用程序中的数据传输尤其是在Web应用程序中与后端服务器通信。 使用JSON的原因总结如下
原因描述易于阅读和编写JSON的结构简单、清晰对人类来说易于阅读和编写轻量级数据格式相较于XML等标记语言JSON更轻量使用更少的符号数据体积更小易于解析和生成大多数编程语言都提供了解析和生成JSON的内置支持或库跨语言支持JSON是独立于语言的被广泛支持和使用在多种编程语言中网络友好JSON格式适合Web环境易于通过网络传输是Web API的常用格式数据互操作性作为一种标准化格式JSON提高了不同系统间的数据互操作性
BS/CS开发过程中会使用不同的编程语言JSON作为数据传输的标准化格式方便程序员协议约定和数据处理
4.2 QT生成JSON数据 在Qt中生成JSON数据并将其保存到文件的一个基本示例涉及使用 QJsonDocument 、 QJsonObject 和QJsonArray 类。以下是一组简单的JSON数据通过程序创建一个简单JSON对象并将对应的JSON数据保存到相应的JSON文件中的示例代码。
JSON数据
{cityId: 1010100,date: 2024-02-22,jsonArray: [data1,data2,100],weather: 雨夹雪
}示例代码
void creatJsonFile()
{// 创建一个JSON对象 键值对QJsonObject rootObj;rootObj[cityId] 1010100;rootObj[date] 2024-02-22;rootObj[weather] 雨夹雪;// 创建一个JSON数组QJsonArray jsonArray;jsonArray.append(data1);jsonArray.append(data2);jsonArray.append(100);// 将数组添加到JSON对象rootObj[jsonArray] jsonArray;/****数据加入对象其他业务程序*****//****数据加入对象其他业务程序*****/// 将JSON对象转换为JSON文档QJsonDocument jsonDoc(rootObj);// 将JSON文档转换为字符串也可以是压缩格式QByteArray datArray jsonDoc.toJson();// 将JSON数据写入文件QFile file(E:/qtProject/00_QT_CLC/weather/test.json);if(!file.open(QIODevice::ReadWrite)){qDebug() ---------file open error----------;}file.write(datArray);file.close();
}说明
创建JSON对象使用 QJsonObject 来构建JSON对象并使用键值对填充数据。创建JSON数组使用 QJsonArray 来创建一个数组并添加元素。组合JSON结构将JSON数组添加到JSON对象中。生成JSON文档通过 QJsonDocument 来处理JSON数据可以选择格式化缩进或压缩形式。保存到文件创建 QFile 对象打开文件写入JSON数据并关闭文件。
上述例子展示了Qt中处理JSON的基础流程包括创建、填充数据、转换为字符串以及写入文件。
补充 也可以根据需要调整这个流程来适应更复杂的JSON结构或数据即在对象中加入子对象在JSON数组中数组的每一项均为对象类型其需要增加的数据如下红框所示。
其中再次添加上述数据的程序如下所示 /****数据加入对象其他业务程序*****/// 创建一个JSON 子对象并添加到JSON对象QJsonObject alarmObj;alarmObj[alarm_type] 雨夹雪;alarmObj[alarm_level] 黄色;alarmObj[alarm_context] 杭州市发布雨夹雪黄色预警;rootObj[alarm] alarmObj;//创建一个数组对象其中数组每一项均为子对象QJsonArray daysArray;QJsonObject day0;day0[day] 星期一;day0[data] 2024-02-22;day0[weather] 晴;day0[temp] 12;//在数组中添加子对象daysArray.append(day0);QJsonObject day1;day1[day] 星期二;day1[data] 2024-02-23;day1[weather] 多云;day1[temp] 10;daysArray.append(day1);QJsonObject day2;day2[day] 星期三;day2[data] 2024-02-24;day2[weather] 晴;day2[temp] 15;daysArray.append(day2);//将JSON数据添加至根对象rootObj[days] daysArray;/****数据加入对象其他业务程序*****/在JSON中数组可以包含多种类型的元素包括对象。当在Qt中处理JSON数组其中的元素是对象时使用 QJsonArray 和 QJsonObject 来创建和处理这些数据结构。以上就是一个示例展示了如何创建一个包含多个对象的JSON数组并将该数组添加到一个JSON对象中。
4.3 QT解析JSON数据 在Qt中解析JSON数据通常涉及到使用 QJsonDocument 、 QJsonObject 和 QJsonArray 类。这些类提供了处理JSON数据的必要工具使您能够从JSON字符串中提取信息、遍历JSON对象或数组并访问具体的数据项。以下是一个基本的示例展示了如何在Qt中解析JSON字符串。
示例解析JSON字符串 假设您有一个JSON字符串例如
{cityId: 1010100,date: 2024-02-22,jsonArray: [data1,data2,100],weather: 雨夹雪
}以下是如何在Qt中解析这个JSON字符串的步骤
void Widget::readJsonFile()
{// 读取JSON文件数据QFile file(E:/qtProject/00_QT_CLC/weather/data.json);if(!file.open(QIODevice::ReadOnly)){qDebug() ---------readJsonFile file open error----------;}QString srcData file.readAll();file.close();// 将JSON字符串转换为QJsonDocumentQJsonDocument jsonDoc QJsonDocument::fromJson(srcData.toUtf8());//JSON文件不为空 且是一个对象if (!jsonDoc.isNull() jsonDoc.isObject()){//创建根对象QJsonObject rootObj jsonDoc.object();//获取根对象下的属性qDebug() ----------获取根对象下的属性-----------;int cityId rootObj[cityId].toInt();QString date rootObj[date].toString();QString weather rootObj[weather].toString();qDebug() cityId: cityId;qDebug() date: date;qDebug() weather: weather;//获取数组jsonArray数据int i 0;if(rootObj.contains(jsonArray) rootObj[jsonArray].isArray()){QJsonArray jsonArray rootObj[jsonArray].toArray();qDebug() ----------获取数组jsonArray数据-----------;for(QJsonValue arr : jsonArray){//qDebug() arr;//判断对象的类型 根据不同的类型进行转化switch (arr.type()){case QJsonValue::String: qDebug() data i : arr.toString(); break;case QJsonValue::Double: qDebug() data i : arr.toDouble(); break;case QJsonValue::Array:break;case QJsonValue::Object:break;case QJsonValue::Bool: qDebug() data i : arr.toBool(); break;default:break;}i;}}}
}说明
字符串转换为 QJsonDocument 使用 QJsonDocument::fromJson 方法将JSON字符串转换为QJsonDocument 对象。提取 QJsonObject 如果 QJsonDocument 包含一个JSON对象使用 object() 方法获取它。访问对象数据使用键如 name 、 age访问 QJsonObject 中的数据。处理数组如果对象包含一个数组使用 QJsonArray 来遍历数组中的元素。
这个示例提供了一个基础框架用于在Qt中解析和处理JSON数据。您可以根据实际需要调整这个过程以适应不同的JSON结构和数据类型。
补充 解析对象中含有子对象与数组的每一项为对象的解析程序 数据 解析程序 //获取alarm子对象数据if(rootObj.contains(alarm) rootObj[alarm].isObject()){QJsonObject alarm rootObj[alarm].toObject();qDebug() ----------获取alarm子对象数据-----------;qDebug() alarm_type: alarm[alarm_type].toString();qDebug() alarm_level: alarm[alarm_level].toString();qDebug() alarm_context: alarm[alarm_context].toString();}//获取数组对象days数据if(rootObj.contains(days) rootObj[days].isArray()){QJsonArray dayArray rootObj[days].toArray();qDebug() ----------获取数组对象days数据-----------;//遍历数组 遍历的每个为obj对象for(QJsonValue day : dayArray){if(day.type() QJsonValue::Object){QString dataStr day[data].toString();QString dayStr day[day].toString();QString weatherStr day[weather].toString();int tempature day[temp].toInt();qDebug() data: dataStr day: dayStr temp: tempature weather: weatherStr;}}}4.4 将JSON数据解析到QMap中 在Qt中如果你想要将JSON数据解析到一个 QMap 中你可以遍历JSON对象的所有键值对并将它们添加到 QMap 里。这个方法特别适合于当你的JSON对象是一个简单的键值对集合时。以下是一个如何实现这一点的示例。
示例将JSON数据解析到QMap中 假设有以下JSON数据
json
{name: John Doe,age: 30,email: john.doeexample.com
}以下是如何将这些数据解析到 QMapQString, QString 中的步骤
oid parseJsonToMap()
{// JSON字符串QString jsonString R({name: John Doe,age: 30,email: john.doeexample.com});// 将JSON字符串转换为QJsonDocumentQJsonDocument jsonDoc QJsonDocument::fromJson(jsonString.toUtf8());// 准备一个QMap来存储解析的数据QMapQString, QString dataMap;// 解析JSON对象并填充QMapif (!jsonDoc.isNull() jsonDoc.isObject()){QJsonObject jsonObj jsonDoc.object();for (auto key : jsonObj.keys()) dataMap[key] jsonObj.value(key).toString();} elseqDebug() Invalid JSON...;// 打印QMap内容for (auto key : dataMap.keys()) qDebug() key : dataMap[key];
}说明
从JSON字符串创建 QJsonDocument 使用QJsonDocument::fromJson 来解析JSON字符串。创建 QMap 定义一个 QMapQString, QString 来存储键值对。遍历JSON对象使用 keys() 方法获取所有键然后遍历这些键将对应的值添加到 QMap 中。打印 QMap 内容遍历 QMap 并打印键值对。
这个示例展示了如何将JSON对象的键值对解析到 QMap 中。这种方法适用于键值对类型的简单JSON对象。对于更复杂的JSON结构可能需要更详细的解析逻辑。
五、软件开发网络通信架构
5.1 BS架构/CS架构 在计算机网络和软件开发中CS架构Client-Server Architecture客户端-服务器架构和BS架构Browser-Server Architecture浏览器-服务器架构是两种主要的应用程序架构。
CS架构客户端-服务器架构 CS架构是一种典型的两层结构包括客户端和服务器两个部分。在这种架构中客户端和服务器通过网络进行通信每部分都有明确的职责。
1. 客户端
用户界面通常在客户端呈现。可以是桌面应用程序、移动应用或专用软件负责向服务器发送请求接收和处理服务器响应
2. 服务器
管理数据和业务逻辑处理来自客户端的请求并发送回响应通常承载在远程系统上如数据库服务器、应用服务器等
3. 特点
需要为每种操作系统或平台单独开发客户端高效的数据处理和响应能力在客户端设备上占用资源如内存和处理能力
BS架构浏览器-服务器架构 BS架构是一种基于Web的三层或多层架构主要通过Web浏览器作为客户端访问服务器上的应用程序。
1. 浏览器客户端
使用标准Web浏览器如Chrome、Firefox等作为客户端无需安装额外的软件使用HTML、CSS和JavaScript显示内容
2. 服务器
和CS架构中的服务器类似处理业务逻辑和数据存储通过Web服务如HTTP服务器提供页面和数据
3. 特点
跨平台兼容性强可以在任何支持Web浏览器的设备上运行客户端无需安装专用软件容易维护和更新可能依赖网络性能因为所有操作都在服务器上进行
对比 部署和维护BS架构易于部署和维护而CS架构通常需要在每个客户端单独安装和更新。性能CS架构可以更有效地利用客户端的计算资源适合高性能要求的应用。BS架构依赖于服务器的性能和网络延迟。安全性CS架构中数据经常在客户端和服务器之间传输可能需要更复杂的安全措施。BS架构中敏感数据主要存储在服务器端。用户体验CS架构通常能提供更丰富的用户界面和交互功能。BS架构的用户体验受限于Web技术的能力。
在实际应用中选择哪种架构取决于具体的业务需求、目标用户群、性能要求以及开发和维护的成本。
5.2 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/htmlapplication/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. Session和Cookies 由于HTTP本身是无状态的Cookies和会话Session被用来在多个请求之间存储用户数据从而为用户提供连贯的体验。
这些概念构成了HTTP的基础是理解和使用HTTP协议的关键。每个概念都有它的具体细节和使用场景了解这些有助于更好地在网络应用开发中应用HTTP。
5.3 Qt中的HTTP编程 主要涉及使用Qt的网络模块来进行HTTP请求和处理HTTP响应。Qt提供了一系列类来处理网络通信其中最常用的类是 QNetworkAccessManager 、 QNetworkRequest 、 QNetworkReply 以及相关的支持类。 以下是一个基本的HTTP编程示例展示了如何使用Qt发送一个简单的HTTP GET请求并处理响应
步骤 1: 包含必要的头文件
#include QCoreApplication
#include QNetworkAccessManager
#include QNetworkRequest
#include QNetworkReply
#include QObject
#include QDebug步骤 2: 发送HTTP请求 创建一个 QNetworkAccessManager 对象并使用它发送HTTP请求。 QNetworkAccessManager 对象会异步地处理请求并返回一个 QNetworkReply 对象。
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QNetworkAccessManager manager;QNetworkRequest request(QUrl(http://example.com));//发起网络请求QNetworkReply *reply manager.get(request);//绑定连接成功与槽函数QObject::connect(reply, QNetworkReply::finished, []() {//应答异常if (reply-error()) {qDebug() Error: reply-errorString();return;}//读取网络返回的JSON数据后续将着重做进一步的处理QString response reply-readAll();qDebug() Response: response;});return a.exec();
}在这个例子中我们使用 QNetworkAccessManager 的 get 方法发送了一个HTTP GET请求到特定网址。然后我们连接了 QNetworkReply 对象的 finished 信号到一个lambda函数该函数在收到HTTP响应时被调用。
注意事项
异步处理: QNetworkAccessManager 的请求是异步的。这意味着 get 方法会立即返回而HTTP响应将在稍后通过信号处理。错误处理: 应该检查 QNetworkReply 对象是否有错误并相应地处理。内存管理: QNetworkReply 对象需要被正确地管理以避免内存泄漏。通常情况下使用QObject::deleteLater 来安排删除它是一个好方法
6. 天气预报项目整合
6.1 连接请求解析JSON数据并刷新界面 通过创建QNetworkAccessManager 进行发起网络请求同时检测QNetworkAccessManager 的finished信号表示接入网络完成通过绑定finished与槽函数用于接收网络连接状态并接收来自网络的JSON数据。
1. 连接网络并绑定槽函数
//由 QNetworkAccessManager 发起get请求
manager new QNetworkAccessManager(this);
//指定请求的url地址
strUrl http://v1.yiketianqi.com/api?unescape1versionv9appid89361488appsecretK6tTmCT0;
QUrl urlYiKeTianQi(strUrl);
QNetworkRequest request(urlYiKeTianQi);
//发起请求
manager-get(request);
//QNetworkReply *reply manager-get(request);//绑定连接请求成功槽函数
connect(manager, QNetworkAccessManager::finished, this, Widget::readHttReply);2. 槽函数检测接入状态并接收数据 槽函数带QNetworkReply 类的参数通过attribute方法获取状态码若访问数据成功则读取网页返回的JSON天气数据用于后续的处理否则异常提示。
//读取HTTP网页请求的数据
void Widget::readHttReply(QNetworkReply *reply)
{//获取状态码int replyCode reply-attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();//qDebug() replyCode: replyCode;//连接成功if(reply-error() QNetworkReply::NoError replyCode 200){//大多数服务器返回utf-8格式QByteArray data reply-readAll();//应答成功对接收到的数据进行JSON解析parseWeatherJsonData(data);//qDebug() QString::fromUtf8(data);}else{qDebug() 网络连接错误: reply-errorString();QMessageBox messageBox;messageBox.setWindowTitle(错误);messageBox.setText(网络连接错误);messageBox.setStyleSheet(QPushButton {color:black});messageBox.setStandardButtons(QMessageBox::Ok);messageBox.exec();}
}3. JSON数据解析 通过封装函数用于单独的数据解析将解析完成数据保存到一个类数组中用于后续的界面刷新调取。
其中Day类的定义如下所示
class Day
{
public:Day();QString mWeek; //星期QString mDate; //日期QString mCity; //城市QString mTemp; //温度QString mWeathType; //天气类型QString mTempLow; //低温QString mTempHigh; //高温QString mTips; //提示QString mFx; //风向QString mFl; //风力QString mPm25; //pm2.5值QString mHu; //湿度QString mAirq; //空气质量
};定义类数组用于保存接下去一周的天气数据
//定义类数组
Day days[6];JSON数据解析函数具体实现如下所示
//解析网页JSON 将数据保存至day类对象数组中 并调用刷新界面函数
void Widget::parseWeatherJsonData(QByteArray srcData)
{// 将JSON字符串转换为QJsonDocumentQJsonDocument jsonDoc QJsonDocument::fromJson(srcData);if (!jsonDoc.isNull() jsonDoc.isObject()){// 将QJsonDocument 转化为 QJsonObject对象QJsonObject rootObj jsonDoc.object();days[0].mCity rootObj[city].toString();days[0].mPm25 rootObj[aqi].toObject()[pm25].toString();if( rootObj.contains(data) rootObj[data].isArray()){QJsonArray weaArray rootObj[data].toArray();//获取七天数据for(int i 0; i 6; i){QJsonObject dayObj weaArray[i].toObject();days[i].mWeek dayObj[week].toString();days[i].mDate dayObj[date].toString();days[i].mWeathType dayObj[wea].toString();days[i].mAirq dayObj[air_level].toString();days[i].mFx dayObj[win].toArray()[0].toString();days[i].mFl dayObj[win_speed].toString();//温度days[i].mTemp dayObj[tem].toString();days[i].mTempLow dayObj[tem2].toString();days[i].mTempHigh dayObj[tem1].toString(); //提示 湿度days[i].mTips dayObj[index].toArray()[3].toObject()[desc].toString();days[i].mHu dayObj[humidity].toString();}}elseqDebug() no array;}//刷新Widget04各标签数据uapateUI();
}4. UI界面刷新数据
通过JSON解析出来的数据将数据刷新到UI界面控件
//并刷新UI界面
void Widget::uapateUI()
{//Widget01 解析日期ui-labelDay-setText(days[0].mDate days[0].mWeek);//Widget02//解析气温 天气ui-labelWeatherPic-setPixmap(weatherPicMap[days[0].mWeathType]);ui-labelWeather-setText(days[0].mWeathType);ui-labelTempData-setText(days[0].mTemp℃);ui-labelTempRange-setText(days[0].mTempLow ℃ - days[0].mTempHigh ℃);ui-labelCity-setText(days[0].mCity);//Widget03//感冒指数ui-labelGanMao-setText(提示: days[0].mTips);//Widget0301//解析风向、空气质量、湿度等ui-labelFengXiangType-setText(days[0].mFx);ui-labelFengXiangData-setText(days[0].mFl);ui-labelPM25Data-setText(days[0].mPm25);ui-labelShiDuData-setText(days[0].mHu);ui-labelAirData-setText(days[0].mAirq);//Widget04 label数据for(int i 0; i 6; i){//日期 时间weekList[i]-setText(days[i].mWeek);weekList[0]-setText(今天);weekList[1]-setText(明天);weekList[2]-setText(后天);QStringList dataList days[i].mDate.split(-); //2024-02-22dateList[i]-setText(dataList[1] - dataList[2]);//天气QPixmap pixmap weatherPicMap[days[i].mWeathType];pixmap.scaled(pixmap.size(), Qt::KeepAspectRatio);weatherPicList[i]-setMaximumHeight(50);weatherPicList[i]-setMaximumWidth(ui-widget-width()/6);weatherPicList[i]-setPixmap(pixmap);weatherTypeList[i]-setText(days[i].mWeathType);//空气质量QString airQuality days[i].mAirq;airQualityList[i]-setText(airQuality);//设置背景颜色if(airQuality 优)airQualityList[i]-setStyleSheet(background-color: rgb(124, 198, 55); border-radius: 8px; color: rgb(230, 230, 230););else if(airQuality 良)airQualityList[i]-setStyleSheet(background-color: rgb(208, 107, 39); border-radius: 8px; color: rgb(230, 230, 230););else if(airQuality 轻度污染)airQualityList[i]-setStyleSheet(background-color: rgb(255, 200, 200); border-radius: 8px; color: rgb(230, 230, 230););else if(airQuality 中度污染)airQualityList[i]-setStyleSheet(background-color: rgb(255, 17, 17); border-radius: 8px; color: rgb(230, 230, 230););else if(airQuality 重度污染)airQualityList[i]-setStyleSheet(background-color: rgb(153, 0, 0); border-radius: 8px; color: rgb(230, 230, 230););//风向 风力fengXiangList[i]-setText(days[i].mFx);fengLiList[i]-setText(days[i].mFl.split(转).at(0));}//更新绘图事件update();
}6.2 支持不同城市查询的实现 通过在网址后添加城市ID即可获取对应城市的天气JSON数据因此核心在于根据行编辑器内的城市名称获取对应的城市id而城市id和城市名称一一对应的关系数据存放在citycode.json文件中。
1. 读取JSON数据存放是QMap容器 通过解析JSON数据将各个城市的名称和id号以键值对的形式保存至QMap容器中方式下次重复解析JSON数据
//将JSON数据读取到Map容器
void cityCodeUtils::initMap()
{// 读取JSON文件数据QFile file(E:/qtProject/00_QT_CLC/weather/citycode.json);if(!file.open(QIODevice::ReadOnly)){qDebug() ---------getCityIdFromName file open error----------;}QString srcData file.readAll();file.close();// 将JSON字符串转换为QJsonDocumentQJsonDocument cityDoc QJsonDocument::fromJson(srcData.toUtf8());if (!cityDoc.isNull() cityDoc.isArray()){//各个城市对象QJsonArray cityArray cityDoc.array();//遍历数组 遍历的每个为obj对象for(QJsonValue citys : cityArray){if(citys.type() QJsonValue::Object){QString city_name citys[city_name].toString();QString city_code citys[city_code].toString();cityMap.insert(city_name,city_code);}}}
}2. 通过城市名称获得城市id 通过QMap中的find方法查找城市名称所对应的城市id同时考虑市、区、县等多种形式的出现若无该城市名称则返回空。
//遍历容器 返回对应城市的城市ID
QString cityCodeUtils::getCityCode(QString cityName)
{if(cityMap.isEmpty())initMap();//查找cityName对应的迭代器并返回值auto pos cityMap.find(cityName);if(pos cityMap.end()){pos cityMap.find(cityName 市);if(pos cityMap.end()){pos cityMap.find(cityName 区);if(pos cityMap.end())pos cityMap.find(cityName 县);if(pos cityMap.end())return ;}}return pos .value();
}3. 搜索按钮槽函数发起新地址访问 在搜索按钮的槽函数中调用获取城市id的函数通过获取文本框内的城市名称得到相应的城市id并将id号拼接至url后重新发起新的网页请求。
//搜索槽函数 点击进行重新发起请求
void Widget::on_btnSearch_clicked()
{QString cityNameInput ui-lineEditSearch-text();cityId cityUtils.getCityCode(cityNameInput);if(cityId ! NULL){//更新带城市信息的网址strUrl http://v1.yiketianqi.com/api?unescape1versionv9appid89361488appsecretK6tTmCT0;//拼接城市号生成新的请求网址strUrl cityid cityId;//发起请求manager-get(QNetworkRequest(QUrl(strUrl)));}else //若无该城市则弹窗提示{QMessageBox messageBox;messageBox.setWindowTitle(错误);messageBox.setText(请出入正确的城市名称);messageBox.move(this-pos().x() 200, this-pos().y() 500);messageBox.setStyleSheet(QPushButton {color:black});messageBox.setStandardButtons(QMessageBox::Ok);messageBox.exec();}
}6.3 七日温度曲线的绘制 ① 因为需要在特定的widget0404和0405上绘制温度曲线而不是在整个大截面绘制温度曲线因此需在构造函数中对widget0404和05两个控制安装事件过滤器器
ui-widget0404-installEventFilter(this);
ui-widget0405-installEventFilter(this);② 在事件过滤函数中检测事件发生对象是否为该两个对象同时是否为画家事件若成立则进行温度曲线的绘制若否则返回QWidget的原始事件
//事件过滤器 过滤widget0404 widget0405有绘图事件时刷新绘图界面
bool Widget::eventFilter(QObject *watched, QEvent *event)
{//widget0404 绘图事件if(watched ui-widget0404 event-type() QEvent::Paint){drawTempLineHight(); //绘制高温曲线图return true; //表示事件已被处理}//widget0405 绘图事件if(watched ui-widget0405 event-type() QEvent::Paint){drawTempLineLow(); //绘制低温曲线图return true; //表示事件已被处理}//返回原始事件return QWidget::eventFilter(watched, event);
}③ 在widget中间绘制不同天气的温度点、线和文字其中点的横坐标为控件的中间位置纵坐标为控件的中间位置与温度和平均位置的差。
//绘制widget0404高温曲线
void Widget::drawTempLineHight()
{QPainter painter(ui-widget0404);//消除边缘混叠painter.setRenderHint(QPainter::Antialiasing,true);//设置画笔与画刷painter.setBrush(QColor(255, 170, 0 ));painter.setPen(QColor(255, 170, 0));//定义6个点QPoint points[6];//计算高温的平均值float ave;int sum 0;for(int i 0; i 6; i){sum days[i].mTempHigh.toInt();}ave sum / 6.0;//qDebug() ave: ave;//绘图for(int i 0; i 6; i){//画点points[i].setX(airQualityList[i]-x() airQualityList[i]-width()/2);points[i].setY(ui-widget0404-height()/2 - (days[i].mTempHigh.toInt() - ave) * 3);painter.drawEllipse(QPoint(points[i].x(), points[i].y()),3,3);//绘制温度painter.drawText(QPoint(points[i].x()-15, points[i].y()-15), days[i].mTempHigh℃);}//画线段for(int i 0; i 5; i)painter.drawLine(points[i], points[i1]);
}