界面没有选择UI布局,使用代码布局为了加深对QT的熟练,看个人爱好
大多数的天气api中不支持自动定位功能,需要手动的设置城市名称,但是这不符合我们实际生活的使用情况,所以在天气api之前我们还需要一个定位ip,这里我使用的是百度ip定位api
https://api.map.baidu.com/location/ip?ak=您的AK&ip=您的IP&coor=bd09ll
AK注册百度开发者平台就可获得
{
"address":"CN|\u56db\u5ddd\u7701|\u6210\u90fd\u5e02|None|None|100|100",
"content":{
"address":"\u56db\u5ddd\u7701\u6210\u90fd\u5e02",
"address_detail":{
"adcode":"510100",
"city":"\u6210\u90fd\u5e02",
"city_code":75,
"district":"",
"province":"\u56db\u5ddd\u7701",
"street":"",
"street_number":""
},
"point":{
"x":"104.07274727",
"y":"30.57899372"
}
},
"status":0
}
第一时间发现不懂,但是状态码表示正常,由于本人也是小白经验不足,也没有提示信息,在这如果觉得麻烦可以换成其他api,比如高德api,但是我死磕了两天搞懂了含义,其实返回的是unicode码,了解了原理过后我们就只要把unicode码转换为汉字就ok了,这里我提供一个转换代码
QString filename;
do
{
int idx = filename.indexOf("\\u");
QString strHex = filename.mid(idx, 6);
strHex = strHex.replace("\\u", QString());
int nHex = strHex.toInt(0, 16);
filename.replace(idx, 6, QChar(nHex));
} while (filename.indexOf("\\u") != -1);
然后得到数据为
{
"address":"CN|四川省|成都市|None|None|100|100",
"content":{
"address":"四川省成都市",
"address_detail":{
"adcode":"510100",
"city":"成都市",
"city_code":75,
"district":"",
"province":"四川省",
"street":"",
"street_number":""
},
"point":{
"x":"104.07274727",
"y":"30.57899372"
}
},
"status":0
}
//发送http请求
void Widget::get_city(void)
{
QNetworkRequest request;
request.setUrl(QUrl("https://api.map.baidu.com/location/ip?ak=您的AK&ip=您的IP&coor=bd09ll"));
requst_city->get(request);
}
//json解析
void Widget::json_city(QNetworkReply *reply)
{
QString all = reply->readAll();
//unicode 转化为汉字
QString filename = all;
do
{
int idx = filename.indexOf("\\u");
QString strHex = filename.mid(idx, 6);
strHex = strHex.replace("\\u", QString());
int nHex = strHex.toInt(0, 16);
filename.replace(idx, 6, QChar(nHex));
} while (filename.indexOf("\\u") != -1);
//json解析过程
QJsonDocument Document;
QJsonParseError json_error;
QJsonDocument json_recv = QJsonDocument::fromJson(all.toUtf8(),&json_error);//解析json对象
QJsonObject object = json_recv.object();
if(object.contains("content"))
{
QJsonValue value = object.value("content");
if(value.isObject())
{
QJsonObject object_1 = value.toObject();
if(object_1.contains("address_detail"))
{
QJsonValue value_1 = object_1.value("address_detail");
if(value_1.isObject())
{
QJsonObject object_2 = value_1.toObject();
locat_city =object_2.value("city").toString();
}
}
}
}
//通过获取了城市自动调用天气数据申请
get_weather(locat_city);
}
一般天气api有三种手动设置获取天气的方式 1、城市中心经纬度; 2、城市编码; 3、城市名。
个人认为城市名方便就以此为例,对应的为墨迹天气api;
http://autodev.openspeech.cn/csp/api/v2.1/weather?openId=aiuicus&clientType=android&sign=android&city=城市名&needMoreData=true&pageNo=1&pageSize=7
{
"code":0,
"msg":"操作成功",
"data":{
"total":7,
"sourceName":"墨迹天气",
"list":[
{
"city":"成都",
"lastUpdateTime":"2022-10-20 18:55:08",
"date":"2022-10-20",
"weather":"晴",
"temp":22.0,
"humidity":"45%",
"wind":"北风1级",
"pm25":58.0,
"pm10":58.0,
"low":14.0,
"high":24.0,
"airData":"58",
"airQuality":"良",
"dateLong":1666195200000,
"weatherType":0,
"windLevel":1,
"province":"四川",
"moreData":{
"sunrise":"2022-10-20 07:09:00",
"sunset":"2022-10-20 18:28:00",
"precipitation":"0",
"alert":null
}
},
上面的json数据不完整,本来会有未来七天的,篇幅有限只展示当天的
void Widget::get_weather(QString city)
{
QNetworkRequest request;
request.setUrl(QUrl(QString("http://autodev.openspeech.cn/csp/api/v2.1/weather?"
"openId=aiuicus&clientType=android&sign=android&city=%1"
"&needMoreData=true&pageNo=1&pageSize=7").arg(city)));
requst_weather->get(request);
}
void Widget::json_weather(QNetworkReply *reply)
{
QString all = reply->readAll();
QJsonDocument Document;
QJsonParseError json_error;
QJsonDocument json_recv = QJsonDocument::fromJson(all.toUtf8(),&json_error);//解析json对象
QJsonObject object = json_recv.object();
if(object.contains("data"))
{
QJsonValue value = object.value("data");
if(value.isObject())
{
QJsonObject object_1 = value.toObject();
if(object_1.contains("list"))
{
QJsonValue value_1 = object_1.value("list");
if(value_1.isArray())
{
for(int i=0; i<7; i++)
{
QJsonObject weather = value_1.toArray().at(i).toObject();
QString strdate = weather.value("date").toString();
date[i] = strdate.right(5);
weather_type[i] = weather.value("weather").toString();
temp[i] = weather.value("temp").toInt();
humidity[i] = weather.value("humidity").toString();
pm[i] = weather.value("pm25").toInt();
int low = weather.value("low").toInt();
int high = weather.value("high").toInt();
temp_range[i] = QString::number(low)+"~~"+QString::number(high)+"℃";
airData[i] = weather.value("airData").toString();
airQuality[i] = weather.value("airQuality").toString();
wind_type[i] = weather.value("wind").toString();
}
}
}
}
}
}
为了不重复造轮子,这里推荐一篇博客,看完基本上qt的json解析都可以掌握
QT json基本用法
//首先请求一个城市定位
get_city();
//每一秒更新一下页面
timer_1 = new QTimer;
connect(timer_1,SIGNAL(timeout()),this,SLOT(data_updata()));
timer_1->start(1000);
//每300秒更新一下天气请求
timer_2 = new QTimer;
connect(timer_2,SIGNAL(timeout()),this,SLOT(get_city()));
timer_2->start(300000);
connect(requst_city, SIGNAL(finished(QNetworkReply*)), this, SLOT(json_city(QNetworkReply*)));
connect(requst_weather, SIGNAL(finished(QNetworkReply*)), this, SLOT(json_weather(QNetworkReply*)));
//搜索其他城市
connect(psearch,SIGNAL(clicked()),this,SLOT(seach_city()));
//手动定位当前城市,并刷新天气数据
connect(plocal, &QToolButton::clicked, [&](){ get_city(); });
void Widget::data_updata()
{
lab_city->setText(locat_city);
//拿到当前系统时间
lab_date[0]->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd dddd"));
//这里是对天气图标的显示,如果打包需要把资源添加到项目中,我这里简单显示效果
lab_weather_type_pic[0]->setPixmap(QPixmap(QString("C:\\Users\\Liu\\Desktop\\code\\QT\\QT_test\\test_city_weather\\img\\%1.png").arg(weather_type[0])));
lab_wendu->setText(QString::number(temp[0]));
lab_weather_type->setText(weather_type[0]);
lab_temp_range[0]->setText(temp_range[0]);
//一些天气指数设置
lab_wind->setText("风 向:"+wind_type[0]);
lab_airD->setText("空气指数:"+airData[0]);
lab_airQ->setText("空气质量:"+airQuality[0]);
lab_pm->setText("PM2.5 :"+QString::number(pm[0]));
lab_hum->setText("湿 度:"+humidity[0]);
//获取其他6天的天气情况
for (int i=1;i<7;i++) {
lab_weather_type_pic[i]->setPixmap(QPixmap(QString("C:\\Users\\Liu\\Desktop\\code\\QT\\QT_test\\test_city_weather\\img\\%1.png").arg(weather_type[i])));
lab_temp_range[i]->setText(temp_range[i]);
lab_date[i]->setText(date[i]);
}
}
这里我写的简单,任意输入一个字符串都会搜索这不对的;
我们应该在这里要去判断输入城市名是否合法性,合法更新界面,不合法提示错误
感兴趣的朋友可以写一下
void Widget::seach_city()
{
locat_city = lsearch->text();
get_weather(locat_city);
data_updata();
}
免费api网站 对于简单的练手api基本上是可以满足的
json解析 帮助小白把json数据格式化方便阅读和写解析代码