Qt项目天气预报(8) - 绘制温度曲线 + 回车搜索(最终篇)

embedded/2024/10/18 18:15:44/

全部内容在专栏

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));}

效果演示

https://img-blog.csdnimg.cn/direct/b8557d38481941bfb2f23f6b0a1a9813.png" width="308" />


 

 画低温曲线

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]);}}

效果演示

https://img-blog.csdnimg.cn/direct/99740577f3c9421e9100da8dc2c053df.png" width="306" />https://img-blog.csdnimg.cn/direct/623497cf2377494cbec106dd034a1111.png" width="307" />



按下回车搜索:

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_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic: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; // 定义全局的urlQNetworkAccessManager *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/101010100QUrl 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 emptyforeach (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.5ui->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.5ui->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();//404qDebug()<<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 匹配 urlurlyiKe += "&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博客

https://img-blog.csdnimg.cn/direct/d6cb2aaf366e464aa0b47b8ea82e9a9c.png" width="336" />

项目总结: 

本次项目包含了qt的很多内容:

光是ui界面搭建就需要花上半天,通过stylelsheet  样式表 的编写 让我们控件更加美观

通过http协议 获得天气API 的json数据

通过json几个常用类(

QJsonDocument  - 表示JSON数据结构,可以包含一个对象(QJsonObject)或数组(QJsonArray)
QJsonObject - 表示JSON对象,即键值对的集合 {}
QJsonArray- 表示JSON数组,即有序的值集合[]

)进行json数据的解析,并把解析到的数据与控件关联起来更新控件数据

同时通过QList去管理多个控件组

通过QPainter 配合事件过滤器去进行温度曲线的绘制 ... 

喜欢的朋友别忘了点赞,收藏,转发,谢谢啦!


http://www.ppmy.cn/embedded/55563.html

相关文章

Spring MVC数据绑定和响应——简单数据绑定(一)默认类型数据绑定

一、Spring MVC常见的默认类型 当使用Spring MVC默认支持的数据类型作为处理器的形参类型时&#xff0c;Spring MVC的参数处理适配器会默认识别这些类型并进行赋值。Spring MVC常见的默认类型如下所示。 • HttpServletRequest&#xff1a;获取请求信息。 • HttpServlet…

算法:链表

目录 链表的技巧和操作总结 常用技巧&#xff1a; 链表中的常用操作 题目一&#xff1a;反转一个单链表 题目二&#xff1a;链表的中间结点 题目三&#xff1a;返回倒数第k个结点 题目四&#xff1a;合并两个有序链表 题目五&#xff1a;移除链表元素 题目六&#xff…

ansible archive模块

用于创建归档文件的模块。它允许你在目标主机上创建tar、zip、gzip、bzip2、xz等类型的归档文件。解压使用unarchive模块。 path&#xff1a;要打包的源目录或文件的路径。&#xff08;可以是单个文件或目录&#xff0c;也可以是包含多个文件和目录的列表。&#xff09;dest&am…

VMware17安装Ubuntu20版本-保姆级别

首先需要安装好VMware和Ubuntu20的镜像&#xff0c;在网上搜索Ubuntu镜像下载即可&#xff0c;最后选择国内镜像站下载&#xff0c;这样更快点&#xff0c;然后打开VMware。 1.创建虚拟机&#xff1a; 2.选择自定义&#xff1a; 3.默认&#xff0c;继续下一步&#xff1a; 4.选…

本地项目上传到GitHub上(李豆)

本地项目上传到GitHub上(李豆) 准备工作&#xff1a; 本地需要有 git 也需要有一个 GitHub 账号 首先需要在 GitHub 新建一个空仓库 在想要上传项目的文件夹中使用 Git 命令操作 初始化&#xff1a; git init与 github 仓库进行链接 &#xff1a;git remote add origin …

【FFmpeg】AVFrame结构体

【FFmpeg】AVFrame结构体 1.AVFrame结构体的定义enum AVPictureType pict_typeAVFrameSideData **side_data 参考&#xff1a; FFMPEG结构体分析&#xff1a;AVFrame 示例工程&#xff1a; 【FFmpeg】调用ffmpeg库实现264软编 【FFmpeg】调用ffmpeg库实现264软解 【FFmpeg】调…

科技创新前沿:Web3在全球发展中的角色

随着数字技术的快速发展&#xff0c;Web3作为新一代互联网技术正逐渐引领着全球科技创新的潮流。本文将深入探讨Web3技术的定义、特点&#xff0c;以及它在全球范围内的应用和未来发展的前景。 1. 引言&#xff1a;Web3技术的定义与演进 Web3是指建立在区块链技术和加密经济学…

Mysql基本操作

文章目录 一、基本概念SQL分类SQL语言规范数据库对象和命名SQL语句分类查看帮助信息查看支持的字符集查看默认使用的字符集修改默认字符集 二、管理数据库新建数据库修改数据库删除数据库查看数据库列表数据类型修饰符表操作DML语言 data manger languageDQL语句 单表查询函数 …