前 言
前段时间开始接触QT,想着没事学习一下QT,这个小列子主要是用到了QJSON 和QNetworkAccessManager 来实现,QJSON 主要是用来json格式文件的解析,QNetworkAccessManager 主要来实现网络请求。
界面展示
界面上看非常low,但是只是demo,主要是学习使用。
代码实现
天气业务类
主要实现天气数据的获取,天气数据的组装与解析,以及通知界面端数据的更新等相关操作,直接上代码:
定义部分代码如下:
/*
* 天气获取类
*/
#ifndef WEATHER_H
#define WEATHER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QMap>
#include <QMultiMap>
class Weather : public QObject
{
Q_OBJECT
public:
explicit Weather(QObject *parent = nullptr);
explicit Weather(QString cityName = "");
public:
void setCityName(QString cityName); //设置城市名
QString getCityName(); //获取城市名
QString getDate(); //获取当前日期
QString getFengLi(); //获取风向风力
QString getWenDu(); //获取温度范围
QString getTianQiType(); //获取天气类型
QString getCurrentWendu(); //获取当前温度
QString getGanMaoInfo(); //获取感冒提示
QString getAllInfo(); //获取原始的所有字段
bool isGetDataSuccessd(); //是否成功获取数据
void refresh(); //刷新
QMap<QString, QMap<QString, QString> > getDataMap(bool *ok=nullptr); //获取昨天以及未来5天的天气预测
void print_Debug_allinfoMap(); //调试打印所有信息
signals:
void getDataFinisedSignal();//获取数据结束的信号
void getDataSuccessedSignal();//获取数据成功的信号
void getDataFailedSignal();//获取数据失败的信号
public slots:
void replyFinished(QNetworkReply *reply);//刷新的槽
private:
void queryWeather();//查询
private:
QString cityName;
QNetworkAccessManager *manager; //请求句柄
QString allinfo; //所有信息
//以下皆是当天,未来几天的数据框通过获取日期的数据列表
QString date;//当前日期
QString fengli; //风力
QString wendu; //温度
QString currentwendu;//当前温度
QString weather_type; //天气类型
QString ganmao;//对于感冒提示
bool isGetData=false;//是否成功获取数据
QMap<QString,QMap<QString,QString>> dataMap;
};
#endif // WEATHER_H
实现部分如下:
/*
* 天气获取类
*/
#include "weather.h"
Weather::Weather(QObject *parent) : QObject(parent)
{
manager = new QNetworkAccessManager(this); //新建QNetworkAccessManager对象
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));//关联信号和槽
}
Weather::Weather(QString cityName)
{
manager = new QNetworkAccessManager(this); //新建QNetworkAccessManager对象
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));//关联信号和槽
this->cityName=cityName;
refresh();
}
void Weather::setCityName(QString cityName)
{
this->cityName=cityName;
}
QString Weather::getCityName()
{
return this->cityName;
}
/*
* 获取当前日期
*/
QString Weather::getDate()
{
return this->date;
}
QString Weather::getFengLi()
{
return this->fengli;
}
QString Weather::getWenDu()
{
return this->wendu;
}
QString Weather::getTianQiType()
{
return this->weather_type;
}
QString Weather::getCurrentWendu()
{
return this->currentwendu;
}
QString Weather::getGanMaoInfo()
{
return this->ganmao;
}
QString Weather::getAllInfo()
{
return this->allinfo;
}
bool Weather::isGetDataSuccessd()
{
return this->isGetData;
}
/*
* 刷新天气
*/
void Weather::refresh()
{
this->currentwendu.clear();
this->wendu.clear();
this->ganmao.clear();
this->fengli.clear();
this->weather_type.clear();
this->allinfo.clear();
queryWeather();
dataMap.clear(); //刷新的清空,待获取时在加载
}
QMap<QString, QMap<QString, QString> > Weather::getDataMap(bool *ok)
{
bool Oktemp;
if(ok==nullptr)
ok=&Oktemp;
if(!this->dataMap.isEmpty())
{
*ok=true;
return this->dataMap;
}
*ok=false;
if(!this->isGetData)
return this->dataMap;
QJsonParseError err;
QJsonDocument json_recv = QJsonDocument::fromJson(allinfo.toUtf8(),&err);//解析json对象
qDebug() <<"Json-Error:"<< err.error;
if(!json_recv.isNull())
{
QJsonObject object = json_recv.object();
QJsonValue value = object.value("data"); // 获取指定 key 对应的 value
if(value.isObject())
{
QJsonObject object_data = value.toObject();
value = object_data.value("daly");
if(value.isArray())
{
QJsonArray valueArray=value.toArray();
qDebug()<<"WeatherData count:"<<valueArray.count();
for(int i=0;i<valueArray.count();i++)
{
QJsonObject object = valueArray.at(i).toObject();
QMap<QString,QString>mapvalue;
mapvalue["high"]=object.value("high").toString();
mapvalue["low"]=object.value("low").toString();
mapvalue["fengxiang"]=object.value("windDirection").toString();
mapvalue["fengli"]=object.value("windScale").toString();
mapvalue["type"]=object.value("weather").toString();
dataMap[object.value("date").toString()]=mapvalue;
}
qDebug()<<QString::fromLocal8Bit("获取天气成功");
*ok=true;
return dataMap;
}
}
}else
{
qDebug()<<"json_recv is NULL or is not a object !!";
}
return dataMap;
}
/*
* qDebug打印Map数据
*/
void Weather::print_Debug_allinfoMap()
{
getDataMap();
qDebug()<<endl;
qDebug()<<"city:"<<this->cityName;
qDebug()<<"wendu:"<<this->wendu;
qDebug()<<"currentwendu:"<<this->currentwendu;
qDebug()<<"fengli:"<<this->fengli;
qDebug()<<"weather_type:"<<this->weather_type;
qDebug()<<"ganmao:"<<this->ganmao;
QString str;
foreach (QString key, dataMap.keys()) {
str="date"+key+"[";
foreach (QString key1, dataMap.value(key).keys()) {
// qDebug()<<key1<<dataMap.value(key).value(key1);
str+=key1+':'+dataMap.value(key).value(key1)+' ';
}
str+=']';
qDebug()<<str;
}
dataMap.clear();
}
void Weather::replyFinished(QNetworkReply *reply)
{
this->isGetData=false;
qDebug()<<"recv weather data!!";
allinfo = reply->readAll();
QJsonParseError err;
QJsonDocument json_recv = QJsonDocument::fromJson(allinfo.toUtf8(),&err);//解析json对象
qDebug() <<"Json-Error:"<< err.error;
if(!json_recv.isNull())
{
QJsonObject object = json_recv.object();
if(object.contains("data"))
{
QJsonValue dateValue = object.value("data"); // 获取指定 key 对应的 value
if(dateValue.isObject())
{
QJsonObject object_data = dateValue.toObject();
QJsonValue value = object_data.value("daly");
if(value.isArray())
{
QJsonObject today_weather = value.toArray().at(0).toObject();
weather_type = today_weather.value("weather").toString();
date = today_weather.value("date").toString();
QString low = today_weather.value("low").toString();
QString high = today_weather.value("high").toString();
wendu = low.mid(low.length()-3,4) +"-"+ high.mid(high.length()-3,4);
QString strength = today_weather.value("windScale").toString();
strength.remove(0,8);
strength.remove(strength.length()-2,2);
fengli = today_weather.value("windDirection").toString() + strength;
//ui->type->setText(weather_type); //显示天气类型
//ui->wendu->setText(wendu); //显示温度
//ui->fengli->setText(fengli); //显示风力
this->isGetData=true;
}
}
}
}else
{
qDebug()<<"json_recv is NULL or is not a object !!";
}
reply->deleteLater(); //销毁请求对象
if(isGetData)
{
qDebug()<<QString::fromLocal8Bit("获取天气成功");
emit this->getDataSuccessedSignal();
}
else
{
qDebug()<<QString::fromLocal8Bit("获取天气失败");
emit this->getDataFailedSignal();
}
emit this->getDataFinisedSignal();
}
/*
* 查询天气
*/
void Weather::queryWeather()
{
// QString local_city = ui->lineEdit->text().trimmed(); //获得需要查询天气的城市名称
//char quest_array[256]="http://wthrcdn.etouch.cn/weather_mini?city=";
char quest_array[256]="http://www.jcznedu.com:5000/weather/prediction/?city=";
QNetworkRequest quest;
sprintf(quest_array,"%s%s",quest_array,cityName.toUtf8().data());
quest.setUrl(QUrl(quest_array));
quest.setHeader(QNetworkRequest::UserAgentHeader,"RT-Thread ART");
/*发送get网络请求*/
manager->get(quest);
}
界面部分代码主要是界面的展示,以及按钮的相应事件。
定义部分:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "weather.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void getWeatherFailedSlot();
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
private:
Ui::Widget *ui;
Weather *weather;
bool isGetData=false;
};
#endif // WIDGET_H
实现部分如下
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMessageBox>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
weather=new Weather(QStringLiteral("合肥"));
connect(weather,&Weather::getDataSuccessedSignal,this,&Widget::on_pushButton_clicked);
connect(weather,SIGNAL(getDataFailedSignal()),this,SLOT(getWeatherFailedSlot()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::getWeatherFailedSlot()
{
QMessageBox::warning(this,QString::fromUtf8("获取天气提示"),QString::fromUtf8("获取天气失败,请确认网络是否连接,或城市名的输入"));
}
void Widget::on_pushButton_clicked()
{
ui->lineEdit_cityName->setText(weather->getCityName());
ui->lineEdit_date->setText(weather->getDate());
ui->lineEdit_currentWendu->setText(weather->getCurrentWendu()+QString::fromLocal8Bit("℃"));
ui->lineEdit_Fengli->setText(weather->getFengLi());
ui->lineEdit_type->setText(weather->getTianQiType());
ui->lineEdit_Wendu->setText(weather->getWenDu());
ui->textBrowser_ganmao->setText(weather->getGanMaoInfo());
ui->tableWidget->clearContents();
ui->tableWidget->setRowCount(0);
QMap<QString,QMap<QString,QString>> map=weather->getDataMap();
int n=0;
foreach (QString date, map.keys()) {
ui->tableWidget->insertRow(ui->tableWidget->rowCount());
QMap<QString,QString> mapvalue=map.value(date);
ui->tableWidget->setItem(n,0,new QTableWidgetItem(date));
ui->tableWidget->setItem(n,1,new QTableWidgetItem(mapvalue.value("type")));
QString low = mapvalue.value("low");
QString high = mapvalue.value("high");
ui->tableWidget->setItem(n,2,new QTableWidgetItem(low.mid(low.length()-3,4) +"-"+ high.mid(high.length()-3,4)));
QString strength = mapvalue.value("fengli");
strength.remove(0,8);
strength.remove(strength.length()-2,2);
ui->tableWidget->setItem(n,3,new QTableWidgetItem(mapvalue.value("fengxiang") + strength));
n++;
}
qDebug()<<weather->getCityName();
qDebug()<<QStringLiteral("风力风向")<<weather->getFengLi();
qDebug()<<QStringLiteral("天气类型")<<weather->getTianQiType();
qDebug()<<QStringLiteral("温度")<<weather->getWenDu();
// ui->textBrowser->setText(weather->getAllInfo());
weather->getDataMap();
}
void Widget::on_pushButton_2_clicked()
{
weather->refresh();
}
void Widget::on_pushButton_3_clicked()
{
if(ui->lineEdit->text().isEmpty())
return;
weather->setCityName(ui->lineEdit->text());
weather->refresh();
}
void Widget::on_pushButton_4_clicked()
{
weather->print_Debug_allinfoMap();
}
总结:
通过上面的代码就可以实现简单的网络请求服务端来展示简单的天气情况,数据源也是在网络上找到的。