全部内容在专栏:
Qt项目 天气预报_mx_jun的博客-CSDN博客
目录
绘制温度曲线
事件过滤器在子控件上绘图
子控件下载事件过滤器
事件过滤器进行绘图 - eventFilter
画初步高温曲线
画初步低温曲线
效果演示
画低温曲线
画高温曲线
效果演示
按下回车搜索:
returnPress()槽函数
整体代码
widget.h
widget.cpp
day.h
day.cpp(无内容)
citycodeutils.h
citycodeutils.cpp
整体ui预览
项目总结:
绘制温度曲线
事件过滤器在子控件上绘图
//难点 -- 我们已经添加了很多控件和样式表,在大的this对象上绘图有难度
//我们可以调用事件过滤器去在子控件上绘图
子控件下载事件过滤器
ui->widget0404->installEventFilter(this);
ui->widget0405->installEventFilter(this);
事件过滤器进行绘图 - eventFilter
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if(watched == ui->widget0404 && event->type() == QEvent::Paint){//在这个控件触发绘图事件,就调用api绘图
drawTempLineHigh();
return true; //表示事件已经被处理
}
if(watched == ui->widget0405 && event->type() == QEvent::Paint){//在这个控件触发绘图事件,就调用api绘图
drawTempLineLow();
return true; //表示事件已经被处理
}
return QWidget::eventFilter(watched, event);
}
画初步高温曲线
void Widget::drawTempLineHigh()
{
//在widget0404 上绘图
QPainter painter(ui->widget0404);
painter.setPen(Qt::yellow);
painter.drawLine(QPoint(10,10),QPoint(30,30));
}
画初步低温曲线
void Widget::drawTempLineLow()
{
//在widget0405 上绘图
QPainter painter(ui->widget0405);
painter.setPen(Qt::yellow);
painter.drawLine(QPoint(10,10),QPoint(30,30));
}
效果演示
画低温曲线
void Widget::drawTempLineLow()
{
//在widget0405 上绘图
QPainter painter(ui->widget0405);
painter.setPen(QColor(70, 192, 203));
painter.setBrush(QColor(70, 192, 203));//设置画刷,让圆变成实心
painter.setRenderHint(QPainter::Antialiasing,true);
// 计算七天最大温度的平均值
int ave;
int sum = 0;
int offset = 0; // 偏移值
int middle = ui->widget0405->height()/2;
for(int i=0;i<6;++i){
sum += day[i].mTempLow.toInt();
}
ave = sum/6;
//定义出6个点
QPoint points[6];
for(int i=0;i<6;++i){
points[i].setX(mAirqList[i]->x() + mAirqList[i]->width()/2); // 设置在对应上方控件的中间位置
offset = (day[i].mTempLow.toInt() - ave)*4; // 计算偏移值
points[i].setY(middle-offset); // 记得y轴正向朝下,so我们这里是-
// 画出6个温度点
painter.drawEllipse(QPoint(points[i]),3,3);
// 画出对应温度
painter.drawText(points[i].x()-15,points[i].y()-15,day[i].mTempLow+"°");
}
//画出5条线将6个点相连接
for(int i=0;i<5;++i){
painter.drawLine(points[i],points[i+1]);
}
}
画高温曲线
void Widget::drawTempLineHigh()
{
//在widget0404 上绘图
QPainter painter(ui->widget0404);
painter.setPen(Qt::yellow);
painter.setBrush(Qt::yellow);//设置画刷,让圆变成实心
painter.setRenderHint(QPainter::Antialiasing,true);
// 计算七天最大温度的平均值
int ave;
int sum = 0;
int offset = 0; // 偏移值
int middle = ui->widget0404->height()/2;
for(int i=0;i<6;++i){
sum += day[i].mTempHigh.toInt();
}
ave = sum/6;
//定义出6个点
QPoint points[6];
for(int i=0;i<6;++i){
points[i].setX(mAirqList[i]->x() + mAirqList[i]->width()/2); // 设置在对应上方控件的中间位置
offset = (day[i].mTempHigh.toInt() - ave)*4; // 计算偏移值
points[i].setY(middle-offset); // 记得y轴正向朝下,so我们这里是-
// 画出6个温度点
painter.drawEllipse(QPoint(points[i]),3,3);
// 画出对应温度
painter.drawText(points[i].x()-15,points[i].y()-15,day[i].mTempHigh+"°");
}
//画出5条线将6个点相连接
for(int i=0;i<5;++i){
painter.drawLine(points[i],points[i+1]);
}
}
效果演示
按下回车搜索:
returnPress()槽函数
//按下回车刷新
void Widget::on_lineEditCity_returnPressed()
{
on_pushButton_clicked(); // 回车被按下,调用搜索槽函数
}
整体代码
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QLabel>
#include <QMenu>
#include <QNetworkReply>
#include <QWidget>
#include <QList>
#include "citycodeutils.h"
#include "day.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Day day[7];
// 定义7个列表去存放我们的label控件内容
QList<QLabel *> mDateList;
QList<QLabel *> mWeekList;
QList<QLabel *> mIconList;
QList<QLabel *> mWeatypeList;
QList<QLabel *> mAirqList;
QList<QLabel *> mFxList;
QList<QLabel *> mFlList;
Widget(QWidget *parent = nullptr);
~Widget();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
bool eventFilter(QObject *watched,QEvent *event);
public slots:
void readHttpReply(QNetworkReply* reply);
private slots:
void on_pushButton_clicked();
void on_lineEditCity_returnPressed();
private:
Ui::Widget *ui;
QMenu *menuQuit;
QPoint mOffset; //偏移值
QNetworkReply* reply;
QString urlyiKe; // 定义全局的url
QNetworkAccessManager *manager;
CityCodeUtils cityCodeUtils;
QMap<QString,QString> mTypeMap;
void parseWeatherJsonData(QByteArray rawData);
void parseWeatherJsonDataNew(QByteArray rawData);// 七天的
void updateUI();
void drawTempLineHigh();
void drawTempLineLow();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMouseEvent>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QMessageBox>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QPainter>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setFixedSize(586,1048); // 固定大小
setWindowFlag(Qt::FramelessWindowHint); //去除上方边框
menuQuit = new QMenu(this);
//设置菜单项文字颜色:白色
menuQuit->setStyleSheet("QMenu::item{color:white}");
//创建行为对象 -- 当调用这种行为打的时候弹出close.png这张图片, 指向这个图片的时候显示"退出"字样
QAction *closeAct = new QAction(QIcon(":/close.png"), tr("退出"), this);
menuQuit->addAction(closeAct); //为menu添加退出行为
// 为menu绑定信号与槽
connect(menuQuit,&QMenu::triggered,this,[=](){
this->close();
});
//由QNetworkAccessManager 发起request请求:
//实例化network对象
manager = new QNetworkAccessManager(this);
connect(manager, &QNetworkAccessManager::finished,[](){
qDebug()<<"manager Finnish!";
});
// http://t.weather.itboy.net/api/weather/city/101010100
QUrl urlItBoy("http://t.weather.itboy.net/api/weather/city/101010100");
//http://v1.yiketianqi.com/api?unescape=1&version=v91&appid=65521391&appsecret=Dv2eKMLL&ext=&cityid=
// 一天
//urlyiKe ="http://v1.yiketianqi.com/api?unescape=1&version=v61&appid=65521391&appsecret=Dv2eKMLL";
//七天
urlyiKe ="http://v1.yiketianqi.com/api?unescape=1&version=v9&appid=65521391&appsecret=Dv2eKMLL";
QUrl urlTianQi(urlyiKe);
//QNetworkRequest - 指定请求的url地址
QNetworkRequest res(urlTianQi); //根据网址实例化QUrl对象,再根据这个对象实例化QNetworkRequest对象
reply = manager->get(res);
//QNetworkReply网络请求后进行信号读取
connect(manager,&QNetworkAccessManager::finished,this,&Widget::readHttpReply);
//初始化七天数据列表
mWeekList<<ui->labelday1<<ui->labelday2
<<ui->labelday3<<ui->labelday4
<<ui->labelday5<<ui->labelday6;
mDateList<<ui->labelDate1<<ui->labelDate2
<<ui->labelDate3<<ui->labelDate4
<<ui->labelDate5<<ui->labelDate6;
mIconList<<ui->labelWeahterIcon0<<ui->labelWeahterIcon1
<<ui->labelWeahterIcon2<<ui->labelWeahterIcon3
<<ui->labelWeahterIcon4<<ui->labelWeahterIcon5;
mWeatypeList<<ui->labelWeatherTypeDate0<<ui->labelWeatherTypeDate1
<<ui->labelWeatherTypeDate2<<ui->labelWeatherTypeDate3
<<ui->labelWeatherTypeDate4<<ui->labelWeatherTypeDate5;
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;
// 根据天气插入对应图标
//根据keys,设置icon的路径
mTypeMap.insert("暴雪",":/type/BaoXue.png");
mTypeMap.insert("暴雨",":/type/BaoYu. png");
mTypeMap.insert("暴雨到大暴雨",":/type/BaoYuDaoDaBaoYu.png");
mTypeMap.insert("大暴雨",":/type/DaBaoYu.png");
mTypeMap.insert("大暴雨到特大暴雨",":/type/DaBaoYuDaoTeDaBaoYu.png");
mTypeMap.insert("大到暴雪",":/type/DaDaoBaoXue.png");
mTypeMap.insert("大雪",":/type/DaXue.png");
mTypeMap.insert("大雨",":/type/DaYu.png");
mTypeMap.insert("冻雨",":/type/DongYu.png");
mTypeMap.insert("多云",":/type/DuoYun.png");
mTypeMap.insert("浮沉",":/type/FuChen.png");
mTypeMap.insert("雷阵雨",":/type/LeiZhenYu.png");
mTypeMap.insert("雷阵雨伴有冰雹",":/type/LeiZhenYuBanYouBingBao.png");
mTypeMap.insert("霾",":/type/Mai.png");
mTypeMap.insert("强沙尘暴",":/type/QiangShaChenBao.png");
mTypeMap.insert("晴",":/type/Qing.png");
mTypeMap.insert("沙尘暴",":/type/ShaChenBao.png");
mTypeMap.insert("特大暴雨",":/type/TeDaBaoYu.png");
mTypeMap.insert("undefined",":/type/undefined.png");
mTypeMap.insert("雾",":/type/Wu.png");
mTypeMap.insert("小到中雪",":/type/XiaoDaoZhongXue.png");
mTypeMap.insert("小到中雨",":/type/XiaoDaoZhongYu.png");
mTypeMap.insert("小雪",":/type/XiaoXue.png");
mTypeMap.insert("小雨",":/type/XiaoYu.png");
mTypeMap.insert("雪",":/type/Xue.png");
mTypeMap.insert("扬沙",":/type/YangSha.png");
mTypeMap.insert("阴",":/type/Yin.png");
mTypeMap.insert("雨",":/type/Yu.png");
mTypeMap.insert("雨夹雪",":/type/YuJiaXue.png");
mTypeMap.insert("阵雪",":/type/ZhenXue.png");
mTypeMap.insert("阵雨",":/type/ZhenYu.png");
mTypeMap.insert("中到大雪",":/type/ZhongDaoDaXue.png");
mTypeMap.insert("中到大雨",":/type/ZhongDaoDaYu.png");
mTypeMap.insert("中雪",":/type/ZhongXue.png");
mTypeMap.insert("中雨",":/type/ZhongYu.png");
//下载事件过滤器
ui->widget0404->installEventFilter(this);
ui->widget0405->installEventFilter(this);
}
/*
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, &QNetworkAccessManager::finished,
this, &MyClass::replyFinished);
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
*/
Widget::~Widget()
{
delete ui;
}
/*
QMenu menu;
QAction *at = actions[0]; // Assumes actions is not empty
foreach (QAction *a, actions)
menu.addAction(a);
menu.exec(pos, at);
*/
//鼠标按下事件
void Widget::mousePressEvent(QMouseEvent *event)
{
//重写鼠标右键事件
if(event->button() == Qt::RightButton){
qDebug()<<"右键";
menuQuit->exec(QCursor::pos()); // 弹出位置为鼠标当前的位置
}
//重写鼠标左键事件 -- 实现拖动窗口
//鼠标当前位置: event->globalPos()
//窗口当前位置:this->pos()
//新窗口位置:
//1.当鼠标左键被按下的时候记录鼠标/窗口当前值,还有鼠标与窗口的相对值 event->pos() --鼠标相对窗口的坐标
//2.鼠标左键释放的时候获得鼠标当前值,对应的窗口位置也根据相对距离进行偏移
if(event->button() == Qt::LeftButton){
qDebug()<<"左键";
//pos() 是相对整个widget页面的坐标 globalpos() 才是相对真个电脑窗口的坐标
//以下两种方式均可得到偏移值
//mOffset = event->globalPos()-this->pos();
mOffset = event->pos();
//qDebug()<<mOffset.x()<<" "<<mOffset.y();
}
}
//鼠标移动事件
void Widget::mouseMoveEvent(QMouseEvent *event)
{
// 将窗口根据鼠标当前位置和偏移值进行移动(这个值是固定的,作为窗口移动的桥梁)
this->move(event->globalPos()-mOffset);
}
// 事件过滤器进行绘图
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if(watched == ui->widget0404 && event->type() == QEvent::Paint){//在这个控件触发绘图事件,就调用api绘图
drawTempLineHigh();
return true; //表示事件已经被处理
}
if(watched == ui->widget0405 && event->type() == QEvent::Paint){//在这个控件触发绘图事件,就调用api绘图
drawTempLineLow();
return true; //表示事件已经被处理
}
return QWidget::eventFilter(watched, event);
}
// 解析获取到的json数据
void Widget::parseWeatherJsonData(QByteArray rawData)
{
QJsonDocument jsonObj = QJsonDocument::fromJson(rawData); // 先把原始数据转为JSON类型
if(!jsonObj.isNull() && jsonObj.isObject()){ // jsonObj不为空,并且是Obeject类型
QJsonObject objRoot = jsonObj.object();
//解析我们获得的json数据, 填入到相关 控件中
//解析日期
QString date = objRoot["date"].toString();
QString week = objRoot["week"].toString();
ui->labelCurrentData->setText(date + " " + week); // 把读取到的日期和星期加入到右上角的控件 labelCurrentData 中
//解析城市名称
QString cityName =objRoot["city"].toString();
ui->labelCity->setText(cityName+"市");
//解析当前温度
QString curTem = objRoot["tem"].toString();
ui->labelTemp->setText(curTem+"℃"); // 显示当前温度
QString lowTem = objRoot["tem2"].toString();
QString highTem = objRoot["tem1"].toString();
ui->labelTempRange->setText(lowTem + "~" +highTem +"℃"); // 显示温度范围
//解析天气类型
ui->labelWeatherType->setText(objRoot["wea"].toString());
ui->labelWeatherIcon->setPixmap(mTypeMap[objRoot["wea"].toString()]); // 根据键值对匹配对应图片
//解析感冒指数
ui->labelGanMao->setText(objRoot["air_tips"].toString());
//解析风向
ui->labelFengXiang->setText(objRoot["win"].toString()); //风向
ui->labelFengXiangData->setText(objRoot["win_speed"].toString());//风力
//解析PM2.5
ui->labelPM25Data ->setText(objRoot["air_pm25"].toString());
//湿度
ui->labelShiDuData->setText(objRoot["humidity"].toString());
//空气质量
ui->labelAriData->setText(objRoot["air_level"].toString());
}
}
//七天json的数据解析
void Widget::parseWeatherJsonDataNew(QByteArray rawData)
{
QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData);
if(!jsonDoc.isNull() && jsonDoc.isObject()){
QJsonObject jsonRoot = jsonDoc.object();
//解析城市
day[0].mCity = jsonRoot["city"].toString();
day[0].mPm25 = jsonRoot["aqi"].toObject()["pm25"].toString();
if(jsonRoot.contains("data") && jsonRoot["data"].isArray()){
QJsonArray weaArray =jsonRoot["data"].toArray();
for(int i=0;i<weaArray.size();++i){ //输出七天情况
QJsonObject obj = weaArray[i].toObject();
qDebug()<<obj["date"].toString()<<obj["wea"].toString();
// 将解析到这七年每天的数据解析到我们的数组中
day[i].mDate = obj["date"].toString();
day[i].mWeek = obj["week"].toString();
day[i].mWeathType = obj["wea"].toString();
day[i].mTemp = obj["tem"].toString();
day[i].mTempLow = obj["tem2"].toString();
day[i].mTempHigh = obj["tem1"].toString();
day[i].mFx = obj["win"].toArray()[0].toString();
day[i].mFl = obj["win_speed"].toString();
day[i].mAirq = obj["air_level"].toString();
// 给出穿建议
//day[i].mTips = obj["air_tips"].toString();
day[i].mTips = obj["index"].toArray()[3].toObject()["desc"].toString();
day[i].mHu = obj["humidity"].toString();
}
}
}
// 定义一个函数去给 ui更新数据
updateUI();
}
// 更新ui界面上的信息
void Widget::updateUI()
{
//解析我们获得的json数据, 填入到相关 控件中
QPixmap pixmap;
//解析日期
ui->labelCurrentData->setText(day[0].mDate + " " + day[0].mWeek); // 把读取到的日期和星期加入到右上角的控件 labelCurrentData 中
//解析城市名称
ui->labelCity->setText(day[0].mCity+"市");
//解析当前温度
ui->labelTemp->setText(day[0].mTemp+"℃"); // 显示当前温度
ui->labelTempRange->setText(day[0].mTempLow + "~" +day[0].mTempHigh +"℃"); // 显示温度范围
//解析天气类型
ui->labelWeatherType->setText(day[0].mWeathType);
ui->labelWeatherIcon->setPixmap(mTypeMap[day[0].mWeathType]); // 根据键值对匹配对应图片
//解析感冒指数
ui->labelGanMao->setText(day[0].mTips);
//解析风向
ui->labelFengXiang->setText(day[0].mFx); //风向
ui->labelFengXiangData->setText(day[0].mFl);//风力
//解析PM2.5
ui->labelPM25Data ->setText(day[0].mPm25);
//湿度
ui->labelShiDuData->setText(day[0].mHu);
//空气质量
ui->labelAriData->setText(day[0].mAirq);
// 更新七个QList的数据
for(int i=0;i<6;++i){
mWeekList[i]->setText(day[i].mWeek);
QStringList daylist = day[i].mDate.split('-'); //分割字符串 -
mDateList[i]->setText(daylist.at(1) + "-" + daylist.at(2)); // 原本是2024-6-24 ,我们只要后两位
// 缩放图标的大小让他能够匹配上
int index =day[i].mWeathType.indexOf("转"); //包含'转'的天气
if(index != -1){//包含'转'
pixmap = mTypeMap[day[i].mWeathType.left(index)]; // 拿到'转'左边的天气图片,例:晴转多云,拿到晴
}
else{
pixmap = mTypeMap[day[i].mWeathType];
}
pixmap = pixmap.scaled(mIconList[i]->size(),Qt::KeepAspectRatio); //缩放图标的大小为图片大小,并用KeepAspectRatio 参数,不让图片被拉伸
mIconList[i]->setPixmap(pixmap);
mWeatypeList[i]->setText(day[i].mWeathType);
// 根据空气质量情况设置对应的颜色
QString airQ = day[i].mAirq;
mAirqList[i]->setText(airQ);
//设置对应样式表
if(airQ == "优"){
mAirqList[i]->setStyleSheet(
"color: rgb(230, 230, 230); background-color: rgb(130, 213, 32); border-radius: 7px");
}
if(airQ == "良"){
mAirqList[i]->setStyleSheet(
"color: rgb(230, 230, 230); background-color: rgb(255, 187, 69); border-radius: 7px");
}
if(airQ == "轻度污染"){
mAirqList[i]->setStyleSheet(
"color: rgb(230, 230, 230);background-color: rgb(239, 121, 24);border-radius: 7px");
}
if(airQ == "中度污染"){
mAirqList[i]->setStyleSheet(
"color: rgb(230, 230, 230); background-color: rgb(255, 17, 17); border-radius: 7px");
}
if(airQ == "重度污染"){
mAirqList[i]->setStyleSheet(
"color: rgb(230, 230, 230); background-color: rgb(153, 0, 0); border-radius: 7px");
}
mFxList[i]->setText(day[i].mFx);
// 风力也会涉及"转",我们设置为左边的即可
index = day[i].mFl.indexOf("转");
if(index != -1){
mFlList[i]->setText(day[i].mFl.left(index));
}
else{
mFlList[i]->setText(day[i].mFl);
}
}
mWeekList[0]->setText("今天");
mWeekList[1]->setText("明天");
mWeekList[2]->setText("后天");
update(); // 调用我们的绘图事件
}
// 画高温曲线
void Widget::drawTempLineHigh()
{
//在widget0404 上绘图
QPainter painter(ui->widget0404);
painter.setPen(Qt::yellow);
painter.setBrush(Qt::yellow);//设置画刷,让圆变成实心
painter.setRenderHint(QPainter::Antialiasing,true);
// 计算七天最大温度的平均值
int ave;
int sum = 0;
int offset = 0; // 偏移值
int middle = ui->widget0404->height()/2;
for(int i=0;i<6;++i){
sum += day[i].mTempHigh.toInt();
}
ave = sum/6;
//定义出6个点
QPoint points[6];
for(int i=0;i<6;++i){
points[i].setX(mAirqList[i]->x() + mAirqList[i]->width()/2); // 设置在对应上方控件的中间位置
offset = (day[i].mTempHigh.toInt() - ave)*4; // 计算偏移值
points[i].setY(middle-offset); // 记得y轴正向朝下,so我们这里是-
// 画出6个温度点
painter.drawEllipse(QPoint(points[i]),3,3);
// 画出对应温度
painter.drawText(points[i].x()-15,points[i].y()-15,day[i].mTempHigh+"°");
}
//画出5条线将6个点相连接
for(int i=0;i<5;++i){
painter.drawLine(points[i],points[i+1]);
}
}
// 画低温曲线
void Widget::drawTempLineLow()
{
//在widget0405 上绘图
QPainter painter(ui->widget0405);
painter.setPen(QColor(70, 192, 203));
painter.setBrush(QColor(70, 192, 203));//设置画刷,让圆变成实心
painter.setRenderHint(QPainter::Antialiasing,true);
// 计算七天最大温度的平均值
int ave;
int sum = 0;
int offset = 0; // 偏移值
int middle = ui->widget0405->height()/2;
for(int i=0;i<6;++i){
sum += day[i].mTempLow.toInt();
}
ave = sum/6;
//定义出6个点
QPoint points[6];
for(int i=0;i<6;++i){
points[i].setX(mAirqList[i]->x() + mAirqList[i]->width()/2); // 设置在对应上方控件的中间位置
offset = (day[i].mTempLow.toInt() - ave)*4; // 计算偏移值
points[i].setY(middle-offset); // 记得y轴正向朝下,so我们这里是-
// 画出6个温度点
painter.drawEllipse(QPoint(points[i]),3,3);
// 画出对应温度
painter.drawText(points[i].x()-15,points[i].y()-15,day[i].mTempLow+"°");
}
//画出5条线将6个点相连接
for(int i=0;i<5;++i){
painter.drawLine(points[i],points[i+1]);
}
}
//http网络请求后进行读取槽函数
void Widget::readHttpReply(QNetworkReply* reply)
{
int resCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();//404
qDebug()<<resCode;
if(reply->error() == QNetworkReply::NoError && resCode == 200){ // 没出错的情况下执行
//大多数服务器网址返回的编码格式是 utf-8,需要进行格式转化
QByteArray data = reply->readAll();
//parseWeatherJsonData(data);
parseWeatherJsonDataNew(data);
//qDebug()<<QString::fromUtf8(data); // 将读到utf-8格式的数据转为QString类型进行输出
}
else{
//qDebug()<<"请求失败"<<reply->errorString();
QMessageBox msg;
msg.setWindowTitle("错误");
msg.setText("网络请求失败!");
msg.setStyleSheet("QPushButton{color:red};");//设置按钮样式
msg.setStandardButtons(QMessageBox::Ok); //添加Ok按钮
msg.exec();// 调用QMessageBox对象
}
}
//根据用户输入城市名字获取数据
void Widget::on_pushButton_clicked()
{
QString cityNameFromUser = ui->lineEditCity->text();
QString cityCode = cityCodeUtils.getCityCodeFromName(cityNameFromUser);
if(cityCode != ""){ // 能匹配到根据城市id 匹配 url
urlyiKe += "&cityid=" +cityCode;
qDebug()<<urlyiKe;
manager->get(QNetworkRequest(QUrl(urlyiKe)));
}
else{ // 没找到
QMessageBox msg;
msg.setWindowTitle("错误");
msg.setText("请输入正确的城市名称!");
msg.setStyleSheet("QPushButton{color:red};");//设置按钮样式
msg.setStandardButtons(QMessageBox::Ok); //添加Ok按钮
msg.exec();// 调用QMessageBox对象
}
}
//按下回车刷新
void Widget::on_lineEditCity_returnPressed()
{
on_pushButton_clicked(); // 回车被按下,调用搜索槽函数
}
day.h
#ifndef DAY_H
#define DAY_H
#include <QString>
class Day
{
public:
Day();
QString mDate;
QString mWeek;
QString mCity;
QString mTemp;
QString mWeathType;
QString mTempLow;
QString mTempHigh;
QString mTips;
QString mFx;
QString mFl;
QString mPm25;
QString mHu;
QString mAirq;
};
#endif // DAY_H
day.cpp(无内容)
#include "day.h"
Day::Day()
{
}
citycodeutils.h
#ifndef CITYCODEUTILS_H
#define CITYCODEUTILS_H
#include <QMap>
class CityCodeUtils
{
public:
CityCodeUtils();
QMap<QString,QString> cityMap={};
QString getCityCodeFromName(QString cityName);
void initCityMap();
};
#endif // CITYCODEUTILS_H
citycodeutils.cpp
#include "citycodeutils.h"
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
CityCodeUtils::CityCodeUtils()
{
}
//初始化QMap 并寻找城市名
QString CityCodeUtils::getCityCodeFromName(QString cityName)
{
if(cityMap.isEmpty()){ // 这个map为空就初始化
initCityMap(); // 初始化QMap,把json文件内容中的city_name city_code-以键值对的形式添加到QMap对象cityMao中
}
//根据城市名寻找对应的QMap对象
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 ""; // 四种判断都找不到就返回"" --> 会给出对应QMessageBox的报错
}
return it.value();
}
// 初始化QMap,把json文件内容中的city_name city_code-以键值对的形式添加到QMap对象cityMao中
void CityCodeUtils::initCityMap()
{
QFile file(":/citycode.json");
file.open(QIODevice::ReadOnly);
QByteArray rawData = file.readAll();
file.close();
QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData);
if(jsonDoc.isArray()){
QJsonArray citys = jsonDoc.array();
for(QJsonValue value:citys){
if(value.isObject()){
//读取对应键值对
QString cityName = value["city_name"].toString();
QString cityCode = value["city_code"].toString();
//添加到QMap对象中进行初始化
cityMap.insert(cityName,cityCode);
}
}
}
}
整体ui预览
更详细的ui界面请看第一篇: Qt项目天气预报(1) - ui界面搭建-CSDN博客
项目总结:
本次项目包含了qt的很多内容:
光是ui界面搭建就需要花上半天,通过stylelsheet 样式表 的编写 让我们控件更加美观
通过http协议 获得天气API 的json数据
通过json几个常用类(
QJsonDocument - 表示JSON数据结构,可以包含一个对象(QJsonObject)或数组(QJsonArray)
QJsonObject - 表示JSON对象,即键值对的集合 {}
QJsonArray- 表示JSON数组,即有序的值集合[]
)进行json数据的解析,并把解析到的数据与控件关联起来更新控件数据
同时通过QList去管理多个控件组
通过QPainter 配合事件过滤器去进行温度曲线的绘制 ...
喜欢的朋友别忘了点赞,收藏,转发,谢谢啦!