目录
一、项目概述
1.1项目背景
1.2项目目标
二、功能需求
2.1 用户界面功能
2.2 后台功能
三、技术选择
3.1 开发框架与工具
3.2 第三方 API
四、UI设计
4.1界面展示
4.2stylesheet样式
五、代码实现
1.构造函数
2.网络请求响应处理函数
3.处理json数据
4.更新UI数据
5.城市搜索按钮实现
6.鼠标左键拖动窗口移动右键关闭
7.事件过滤器绘图
六、结果测试
一、项目概述
1.1项目背景
随着人们对生活品质要求的提高,天气预报已成为日常生活的重要组成部分。通过准确的天气信息,用户可以更好地规划出行、穿衣等日常活动。本项目旨在开发一个基于 Qt 框架的天气预报系统,实现实时天气数据的获取、展示以及历史天气数据的查询功能。
1.2项目目标
-
实现天气数据的 HTTP 请求与解析。
-
展示实时天气信息(包括温度、湿度、风速、空气质量等)。
-
提供未来 7 天天气预报功能。
-
提供用户友好的图形界面。
二、功能需求
2.1 用户界面功能
-
实时天气显示:包括当前温度、湿度、风速、天气状况等。
-
未来天气预报:
-
24 小时天气预报(每小时)。
-
7 天天气预报。
-
-
城市切换:用户可以选择不同的城市查看天气信息。
2.2 后台功能
-
HTTP 请求接口实现,用于获取天气数据。
-
JSON 数据解析模块,将接收到的 JSON 格式天气数据转换为程序可用的数据结构。
三、技术选择
3.1 开发框架与工具
-
Qt 框架:用于 GUI 界面开发和应用程序逻辑实现。
-
QNetworkAccessManager:用于 HTTP 请求(API 调用)。
-
JSON 解析库:使用 Qt 提供的
QJsonDocument
类解析天气数据。
3.2 第三方 API
- 使用天气预报服务提供商的 API(如 OpenWeatherMap、WeatherStack 等),实现天气数据接口调用。
易客云天气API免费天气API接口|天气预报接口|全球天气API接口|气象预警|空气质量我直接使用了这个网站提供的接口。
四、UI设计
4.1界面展示
将整个界面分为四部分,命名如对应部分所示,在控件比较多的情况下,注意排版技巧,分模块会更清晰一些,对控件的命名要规律,在后面功能实现的时候编写代码会更顺。
4.2stylesheet样式
设置边框弧度:
border-radius: 4px;
设置某方向边框弧度:
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
设置背景颜色:
background-color: rgba(60, 60, 60, 100);
父控件影响:
QLabel {
background-color: rgba(0, 200, 200, 200);
border-radius: 4px;
}
五、代码实现
1.构造函数
使用Qt框架创建了一个无边框窗口,固定大小为411x850像素,并设置Arial字体大小为15。创建了一个包含“退出”操作的下拉菜单。点击该菜单项会触发关闭当前窗口的操作。使用QNetworkAccessManager
发送HTTP GET请求到指定天气API接口,以获取实时天气数据。定义了处理网络响应的槽函数readHttpReply
,当网络请求完成时将调用该函数来处理返回的数据。
2.网络请求响应处理函数
-
获取并打印HTTP状态码:从
QNetworkReply
对象中提取HTTP状态码,并将其输出到调试控制台。这有助于在开发和调试过程中快速判断网络请求的成功与否。 -
检查网络请求是否成功:使用
reply->error()
方法检查是否存在网络错误,同时验证HTTP状态码是否为200(表示成功的响应)。如果这两个条件都满足,则认为请求是成功的。 -
处理成功的网络响应:读取所有来自服务器的响应数据,并将其传递给新的解析函数
parseWeatherJsonDataNew(data);
。这表明代码中有专门的函数来解析JSON格式的数据,以便提取有用的信息(如天气数据)进行后续处理或显示。 -
处理失败的网络响应:如果网络请求出现错误(如连接超时、服务器不可达等),则创建并显示一个警告对话框。该对话框提示用户请求失败,并且按钮的文字颜色被设置为红色以增强视觉效果。
3.处理json数据
4.更新UI数据
void Widget::updateUI()
{ui->labelCurrentData->setText(days[0].mDate+" "+days[0].mWeek);//解析城市名称ui->labelCity->setText(days[0].mCity+"市");//解析当前温度ui->labelTemp->setText(days[0].mTemp+"°");ui->labelTempRange->setText(days[0].mTempLow+"℃"+"~"+days[0].mTempHigh+"℃");//解析天气类型ui->labelweatherType->setText(days[0].mWeathType);ui->labelWeatherIcon->setPixmap(mTypeMap[days[0].mWeathType]);//感冒指数ui->labelGanmao->setText(days[0].mTips);//风向ui->labelFXType->setText(days[0].mFx);//风力ui->labelFXType_3->setText(days[0].mFl);//PM2.5ui->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.at(1)+"-"+dayList.at(2));int index = days[i].mWeathType.indexOf("转");
// if(index!=-1){
// qDebug()<<days[i].mWeathType.left(index);
// mIconList[i]->setPixmap(mTypeMap[days[i].mWeathType.left(index)]);
// mWeaTypeList[i]->setText(days[i].mWeathType.left(index));
// }mIconList[i]->setPixmap(mTypeMap[days[i].mWeathType]);mWeaTypeList[i]->setText(days[i].mWeathType);QString airQ = days[i].mAirq;mAirqList[i]->setText(airQ);if(airQ=="优"){mAirqList[i]->setStyleSheet("background-color : rgb(150,213,32);border-radius: 7px;");}if(airQ=="良"){mAirqList[i]->setStyleSheet("background-color : rgb(241,224,103);border-radius: 7px;");}if(airQ=="轻度污染"){mAirqList[i]->setStyleSheet("background-color : rgb(255,199,199);border-radius: 7px;");}if(airQ=="中度污染"){mAirqList[i]->setStyleSheet("background-color : rgb(255,17,17);border-radius: 7px;");}if(airQ=="重度污染"){mAirqList[i]->setStyleSheet("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();}