前言:
QT获取天气信息一般都是通过调用天气服务器的接口来获取的,网上有很多免费的天气信息API,大致分为两种,一种是xml编码格式的天气信息,一种是Json编码格式的天气信息。Qt对于Json和xml格式文件都有自己的解析方式,而解析Json更为简单、方便,所以选择解析Json格式的天气信息API:http://t.weather.sojson.com/api/weather/city/101010100 (后面最后一个为城市ID)
一、设计目标
1、用Qt的HTTP通信,获取天气API的内容,再进行解析,实现连续五天的天气查询显示
2、实现对多个城市的天气信息进行查询,下面提供城市的ID
合肥 | 101220101 |
北京 | 101010100 |
襄阳 | 101200201 |
广州 | 101280101 |
二、实现过程
1、界面设计
如下图所示,天气窗口界面由图中①、②、③三部分。其中:
(1)第①部分包括日期框和时间框(QLabel),城市输入框(QComboBox),搜索按钮(QPushButton)。
(2)第②部分是显示今天的天气,包括天气类型显示框,天气图标框、当前温度、温度范围、风力以及空气质量。
(3)第③部分是接下来四天的天气显示地方,每一天由七个QLabel组成,分别显示周几、几月几号、天气图标、温度范围、天气、风力以及空气质量
2、工程目录解析
3、源代码分析
1、通过HTTP获取天气信息的流程(json格式)
(1)创建QNetworkAccessManager对象
(2)调用对象方法get/post发送请求(附带一个请求对象)
① 选择相应的URL
② 创建一个请求对象
③ 通过get发送请求
(3)当请求完毕后有数据返回时,QNetworkAccessManager对象会发送finished信号,这样就会调用read_data函 数
(4).在槽函数中获取应答对象并且通过应答对象读取服务器返回的数据
2、解析读到的json格式数据
Json格式的数据是以“{}”包含,Qt把这整体数据叫做“JsonDocument”,相当于目录,并且提供了QJsonDocument类来将信息转换为Qt能够解析的Json数据格式,和QJsonParseError类来检测数据是不是Json格式。“{}”里面存放的是键值对,键值对格式为 key:value key为键,value为值,value可以是对象,数组, 数,字符串。
(1)判断是否为json格式的数据,如果不是json格式,则程序自动退出
(2)json格式一层一层解析
① 如果键对应的值为数或字符串时,里面的内容叫做“QJsonObject”,可以由QJsonDocument的“object()”方法来获取
② 如果键对应的值为数组时,里面的内容叫做“QJsonArray”,再通过遍历将数组将数据取出来(我这里的json数据里面的数组都是存放的键值对,且键值对存放的内容为字符串)
③ 如果键对应的值为对象时,则需要进一步的解析
3、关键代码已经向大家解释了,现在附上源代码
#include "weather.h"
#include "ui_weather.h"
Weather::Weather(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Weather)
{
ui->setupUi(this);
//num达到一定值时刷新天气
num = 0;
this->rangewendu[0] = ui->range_wendu1;
this->rangewendu[1] = ui->range_wendu2;
this->rangewendu[2] = ui->range_wendu3;
this->rangewendu[3] = ui->range_wendu4;
this->rangewendu[4] = ui->range_wendu5;
wtpye[0] = ui->typelb1;
wtpye[1] = ui->typelb2;
wtpye[2] = ui->typelb3;
wtpye[3] = ui->typelb4;
wtpye[4] = ui->typelb5;
windlb[0] = ui->windlb1;
windlb[1] = ui->windlb2;
windlb[2] = ui->windlb3;
windlb[3] = ui->windlb4;
windlb[4] = ui->windlb5;
aqilb[0] = ui->aqilb1;
aqilb[1] = ui->aqilb2;
aqilb[2] = ui->aqilb3;
aqilb[3] = ui->aqilb4;
aqilb[4] = ui->aqilb5;
weeklb[1] =ui->weeklb2;
weeklb[2] =ui->weeklb3;
weeklb[3] =ui->weeklb4;
weeklb[4] =ui->weeklb5;
datalb[1] = ui->datalb2;
datalb[2] = ui->datalb3;
datalb[3] = ui->datalb4;
datalb[4] = ui->datalb5;
typepiclb[0] = ui->typepiclb1;
typepiclb[1] = ui->typepiclb2;
typepiclb[2] = ui->typepiclb3;
typepiclb[3] = ui->typepiclb4;
typepiclb[4] = ui->typepiclb5;
//天气url
QUrl url("http://t.weather.sojson.com/api/weather/city/101200201");
//创建一个请求对象
QNetworkRequest request(url);
manager.get(request);
//关联finished信号
connect(&manager,&QNetworkAccessManager::finished,this,&Weather::read_data);
//获取时间以及刷新天气页面
mtimer.start(1000);
connect(&mtimer,&QTimer::timeout,this,&Weather::run);
}
Weather::~Weather()
{
delete ui;
}
//判断空气指数是哪个级别
void Weather::aqi_result(int aqi,int i)
{
QString aqi_rank;
if(aqi<=50) {aqi_rank ="优";aqilb[i]->setStyleSheet("background-color:#55ff7f");}
else if(aqi<=100) {aqi_rank ="良"; aqilb[i]->setStyleSheet("background-color:#ffff00");}
else if(aqi<=150) {aqi_rank ="轻度污染";aqilb[i]->setStyleSheet("background-color:#ffaa00");}
else if(aqi<=200) {aqi_rank ="中度污染";aqilb[i]->setStyleSheet("background-color:#ff5500");}
else if(aqi<=300) {aqi_rank ="重污染";aqilb[i]->setStyleSheet("background-color:#b83d00"); }
else {aqi_rank ="严重污染";aqilb[i]->setStyleSheet("background-color:#686868"); }
qDebug()<<aqi_rank;
aqilb[i]->setText(QString::number(aqi)+" "+aqi_rank);
}
//判断天气
void Weather::type_result(QString type,int i)
{
QString path;
if(type == "晴"){path = ":/images/images/晴.png";}
else if(type=="多云" || type == "晴转多云"){path = ":/image/images/多云.png";}
else if(type=="阴"){path = ":/image/images/阴.png";}
else if(type=="阵雨"){path = ":/image/images/阵雨.png";}
else if(type=="雷阵雨"){path = ":/image/images/雷阵雨.png";}
else if(type=="小雨"){path = ":/image/images/小雨.png";}
else if(type=="中雨"){path = ":/image/images/中雨.png";}
else if(type=="大雨"){path = ":/image/images/大雨.png";}
else if(type=="暴雨"){path = ":/image/images/暴雨.png";}
else if(type =="大暴雨"||type =="大到暴雨"){path = ":/image/images/特大暴雨.png";}
else {path = ":/image/images/扬沙.png";}
typepiclb[i]->setPixmap(QPixmap(path));
}
void Weather::background_main(QString weatherpic)
{
if(weatherpic=="晴"||weatherpic == "多云" ||weatherpic == "晴转多云"||weatherpic=="阴")
{
this->setStyleSheet("QMainWindow{border-image:url(:/image/images/UI.png)}");
}
else this->setStyleSheet("QMainWindow{border-image:url(:/image/images/UI5.png)}");
}
void Weather::read_data(QNetworkReply *reply)
{
QByteArray array = reply->readAll();
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(array,&error);
if(error.error !=QJsonParseError::NoError)
{
qDebug("josn error");
return ;
}
QJsonObject obj = doc.object();
//时间
QString time = obj.value("time").toString();
time = time.mid(5,5);
qDebug()<<time;
//地区
QJsonObject cityobj = obj.value("cityInfo").toObject();
QString city = cityobj.value("city").toString();
qDebug()<<city;
QJsonObject dataobj = obj.value("data").toObject();
//实时温度
QString wendu = dataobj.value("wendu").toString();
qDebug()<<wendu;
ui->wendu->setText(wendu);
//近一周的天气
QJsonArray forecast_array = dataobj.value("forecast").toArray();
for(int i =0;i<5;i++)
{
QJsonObject weatherobj = forecast_array.at(i).toObject();
//最高温度
QString high = weatherobj.value("high").toString();
high = high.mid(3);
qDebug()<<high;
//最低温度
QString low = weatherobj.value("low").toString();
low = low.mid(3,2);
qDebug()<<low;
//温度范围
QString range_wendu = low+"~"+high;
qDebug()<<range_wendu;
rangewendu[i]->setText(range_wendu);
//日期
QString ymd = weatherobj.value("ymd").toString();
ymd = ymd.mid(5);
qDebug()<<ymd;
//星期几
week[i] =weatherobj.value("week").toString();
qDebug()<<week[i];
if(i!=0){
weeklb[i]->setText(week[i]);
datalb[i]->setText(ymd);
}
//天气
QString type = weatherobj.value("type").toString();
qDebug()<<type;
if(i == 0) weatherpic = type;
wtpye[i]->setText(type);
type_result(type,i);
//风
QString fx = weatherobj.value("fx").toString();
QString fl = weatherobj.value("fl").toString();
QString wind = fx+fl;
qDebug()<<wind;
windlb[i]->setText(wind);
//空气质量
int aqi = weatherobj.value("aqi").toInt();
qDebug()<<aqi;
aqi_result(aqi,i);
}
//地区+日期+星期
ui->datalb->setText(city+" "+time+" "+week[0]);
//设置QMainWindow的背景
background_main(weatherpic);
//实时天气
ui->currweatherlb->setText(weatherpic+"实时");
}
void Weather::on_pushButton_clicked()
{
QString ip;
//通过获取城市输入框的当前值来选择哪个城市的URL
QString city = ui->comboBox->currentText();
if(city =="北京"){ip = "http://t.weather.sojson.com/api/weather/city/101010100";}
else if(city=="广州"){ip = "http://t.weather.sojson.com/api/weather/city/101280101";}
else if(city=="合肥"){ip = "http://t.weather.sojson.com/api/weather/city/101220101";}
else if(city=="襄阳"){ip = "http://t.weather.sojson.com/api/weather/city/101200201";}
//天气url
QUrl url(ip);
//创建一个请求对象
QNetworkRequest request(url);
manager.get(request);
}
void Weather::run()
{
QString time = QTime::currentTime().toString("hh:mm:ss");
ui->timelb->setText(time);
num++;
//隔五分钟刷新一次
if(num>=60*5){on_pushButton_clicked();num = 0;}
}
头文件
#ifndef WEATHER_H
#define WEATHER_H
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonValue>
#include <QJsonParseError>
#include <QJsonObject>
#include <QLabel>
#include <QTimer>
#include <QTime>
namespace Ui {
class Weather;
}
class Weather : public QMainWindow
{
Q_OBJECT
public:
explicit Weather(QWidget *parent = nullptr);
~Weather();
void aqi_result(int aqi,int i);
void type_result(QString type, int i);
void background_main(QString weatherpic);
protected slots:
void run();
private slots:
void read_data(QNetworkReply *reply);
void on_pushButton_clicked();
private:
Ui::Weather *ui;
QNetworkAccessManager manager;
QString weatherpic;
QString week[5];
QLabel *rangewendu[5];
QLabel *wtpye[5];
QLabel *windlb[5];
QLabel *aqilb[5];
QLabel *weeklb[5];
QLabel *datalb[5];
QLabel *typepiclb[5];
QTimer mtimer;
int num;
};
#endif // WEATHER_H