QT实现天气预报

1. MainWindow类设计的成员变量和方法

public:
MainWindow(QWidget* parent = nullptr);
~MainWindow();

protected:

形成文本菜单来用来右键关闭窗口
void contextMenuEvent(QContextMenuEvent* event);

鼠标被点击之后此事件被调用

void mousePressEvent(QMouseEvent *ev);

移动窗口
void mouseMoveEvent(QMouseEvent* ev);
//重写过滤器方法
bool eventFilter(QObject *watched, QEvent *event);

private slots://信号槽函数
void onReplied(QNetworkReply* reply);

void on_btnSearch_clicked();

public:

void getWeaterInfo(QString cityCode);
//解析json数据
void parseJson(QByteArray& byteArray);
int parseString(QString str);
//更新UI
void UpdateUi();
//检测空气质量
int checkedQulity(int api);
//绘制高低温曲线
void paintHighCurve();
void paintLowCurve();

private:
Ui::MainWindow* ui;

QMenu* mExitMenu; // 右键退出的菜单
QAction* mExitAct; // 退出的行为
QPoint m_offset;//鼠标和左上角坐标的偏移距离
QNetworkAccessManager *m_netAccessManager;
Today m_today;
Day m_day[7];

//星期和日期
QList<QLabel*> m_weekList;
QList<QLabel*> m_dateList;

//天气和天气图标
QList<QLabel*> m_typeList;
QList<QLabel*> m_typeIconList;

//天气污染指数
QList<QLabel*> m_ApiList;

//风力和风向
QList<QLabel*> m_FLList;
QList<QLabel*> m_FXList;

把UI控件都放到QList集合里面

cpp 复制代码
//将UI控件放到数组里边,方便使用循环进行处理
    m_dateList << ui->lblDate0 << ui->lblDate1 << ui->lblDate2 << ui->lblDate3 << ui->lblDate4 << ui->lblDate5;
    m_weekList << ui->lblWeek0 << ui->lblWeek1 << ui->lblWeek2 << ui->lblWeek3 << ui->lblWeek4 << ui->lblWeek5;
    m_ApiList << ui->lblQuality0 << ui->lblQuality1 << ui->lblQuality2 << ui->lblQuality3 << ui->lblQuality4 << ui->lblQuality5;
    m_typeList << ui->lblType0 << ui->lblType1 << ui->lblType2 << ui->lblType3 << ui->lblType4 << ui->lblType5;
    m_typeIconList << ui->lblTypeIcon0 << ui->lblTypeIcon1 << ui->lblTypeIcon2 << ui->lblTypeIcon3 << ui->lblTypeIcon4 << ui->lblTypeIcon5;
    m_FXList << ui->lblFx0 << ui->lblFx1 << ui->lblFx2 << ui->lblFx3 << ui->lblFx4 << ui->lblFx5;
    m_FLList << ui->lblFl0 << ui->lblFl1 << ui->lblFl2 << ui->lblFl3 << ui->lblFl4 << ui->lblFl5;

QMap <QString,QString> m_typeMap;

2. 右键退出

void contextMenuEvent(QContextMenuEvent* event);

cpp 复制代码
  mExitMenu->exec(QCursor::pos());
    event->accept();

QMenu* mExitMenu; 右键退出的菜单

// 右键菜单:退出程序
mExitMenu = new QMenu(this);//添加一个菜单框
mExitAct = new QAction();
mExitAct->setText(tr("退出"));
mExitAct->setIcon(QIcon(":/res/close.png"));
mExitMenu->addAction(mExitAct);//把这个行为设置到菜单里面去

connect(mExitAct, &QAction::triggered, this, [=]() {
qApp->exit(0);
});

3.存放天气信息的类

cpp 复制代码
class Today
{
public:
    Today()
    {
        date = "2022-10-20";
        city = "广州";

        ganmao = "感冒指数";

        wendu = 0;
        shidu = "0%";
        pm25 = 0;
        quality = "无数据";

        type = "多云";

        fl = "2级";
        fx = "南风";

        high = 30;
        low = 18;
    }

    QString date;
    QString city;

    QString ganmao;

    int wendu;
    QString shidu;
    int pm25;
    QString quality;

    QString type;

    QString fx;
    QString fl;

    int high;
    int low;
};

class Day
{
public:
    Day()
    {
        date = "2022-10-20";
        week = "周五";

        type = "多云";

        high = 0;
        low = 0;

        fx = "南风";
        fl = "2级";

        aqi = 0;
    }

    QString date;
    QString week;

    QString type;
    QString ymd;

    int high;
    int low;

    QString fx;
    QString fl;

    int aqi;
};

4.get请求数据

cpp 复制代码
void MainWindow::getWeaterInfo(QString cityName)
{
    QString cityCode=weatherTool::getCityCode(cityName);
    qDebug()<<"cityCode"<<cityCode;
    QUrl url("http://t.weather.itboy.net/api/weather/city/"+cityCode);
    m_netAccessManager->get(QNetworkRequest(url));//发送get请求
}

5.重写void onReplied函数

void onReplied(QNetworkReply* reply);在get请求成功之后此函数被调用

cpp 复制代码
void MainWindow::onReplied(QNetworkReply *reply)
{
    qDebug()<<"onReplied success";
    int status_code=reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug()<<"参数: "<<reply->operation();
    qDebug()<<"状态码: "<<status_code;
        qDebug()<<"url: "<<reply->url();
    qDebug()<<"请求头: "<<reply->rawHeaderList();
                                   
    if(reply->error()!=QNetworkReply::NoError||status_code!=200){
        qDebug()<<reply->errorString().toLatin1().data();
        QMessageBox::warning(this,"天气预报","数据请求失败",QMessageBox::Ok);
    }
    else{
        QByteArray all=reply->readAll();

        qDebug()<<"read all : "<<all.data() ;
        parseJson(all);
    }
    reply->deleteLater();

}

在此函数里把请求到的数据全部读出来

6.读出类之后在调用parseJson(all);来进行解析JSON数据

cpp 复制代码
void MainWindow::parseJson(QByteArray &byteArray)
{
    QJsonParseError err;
    QJsonDocument doc=QJsonDocument::fromJson(byteArray,&err);
    if(err.error!=QJsonParseError::NoError){
        qDebug()<<"解析Json出错了";
        return ;
    }

    //Json对象,包括了请求的全部数据
    QJsonObject rootObj = doc.object();
    //qDebug() << rootObj;
    QJsonObject dataObj = rootObj.value("data").toObject();
    QJsonObject yesterdayObj = dataObj.value("yesterday").toObject();
    //Json数组,未来几天的数据
    QJsonArray forecastArray = dataObj.value("forecast").toArray();
    //1.解析日期和城市
   QString str = rootObj.value("time").toString();
    m_today.date= str.split(" ").at(0);
    qDebug()<<"今天:"<<m_today.date;
    m_today.city = rootObj.value("cityInfo").toObject().value("city").toString();

    //2.解析yesterday
    m_day[0].date = yesterdayObj.value("date").toString();//日期
    m_day[0].aqi = yesterdayObj.value("aqi").toDouble();//空气质量,toDouble包括整数型
    m_day[0].type = yesterdayObj.value("type").toString();//天气类型
    m_day[0].week = yesterdayObj.value("week").toString();//星期
    m_day[0].ymd = yesterdayObj.value("ymd").toString();//完整年月日
    //解析最低温度和最高温度
    /*
    QString str = yesterdayObj.value("low").toString();//最低温度
    str = str.split(" ").at(1);//以空格为分割符,去除前面的文字,取出第二个X℃,
    str = str.left(str.length() - 1);//去除后面的摄氏度符号
    mDay[0].low = str.toInt();//传入最低温度
    str.clear();//清除内容
    str = yesterdayObj.value("high").toString();//最高温度
    str = str.split(" ").at(1);//以空格为分割符,去除前面的文字,取出第二个X℃,
    str = str.left(str.length() - 1);//去除后面的摄氏度符号
    mDay[0].high = str.toInt();//传入最高温度
    */
    //简化版
    m_day[0].low = parseString(yesterdayObj.value("low").toString());//最低温度
    m_day[0].high = parseString(yesterdayObj.value("high").toString());//最高温度
    m_day[0].fx = yesterdayObj.value("fx").toString();//风向
    m_day[0].fl = yesterdayObj.value("fl").toString();//风力

    //3.解析forecast中的6天数据

    for (int i = 0; i < 5; ++i) {
        QJsonObject forecastData = forecastArray[i].toObject();
        //跳过0,因为0已经赋值给昨天的数据了
        m_day[i + 1].date = forecastData.value("date").toString();//日期
        //qDebug()<<"time: "<<m_day[i + 1].date;
        m_day[i + 1].aqi = forecastData.value("aqi").toDouble();//空气质量,toDouble包括整数型
        m_day[i + 1].type = forecastData.value("type").toString();//天气类型
        m_day[i + 1].week = forecastData.value("week").toString();//星期
        m_day[i + 1].low = parseString(forecastData.value("low").toString());//最低温度
        m_day[i + 1].high = parseString(forecastData.value("high").toString());//最高温度
        m_day[i + 1].fx = forecastData.value("fx").toString();//风向
        m_day[i + 1].fl = forecastData.value("fl").toString();//风力
        m_day[i + 1].ymd = forecastData.value("ymd").toString();//完整年月日
        //ymd分割成MM/dd
        //QDateTime::fromString(forecastData.value("ymd").toString(), "yyyy-MM-dd").toString("MM/dd");//日期
        //qDebug() << i << mDay[i + 1].date << mDay[i + 1].aqi << mDay[i + 1].type << mDay[i + 1].week << mDay[i + 1].low << mDay[i + 1].high << mDay[i + 1].fx << mDay[i + 1].fl;
        //qDebug() << i << mDay[i].date;
        //qDebug() << mDay[i + 1].ymd;
    }
    //4.解析今天的数据
    m_today.shidu = dataObj.value("shidu").toString();
    m_today.quality = dataObj.value("quality").toString();
    m_today.ganmao = dataObj.value("ganmao").toString();
    m_today.pm25 = dataObj.value("pm25").toDouble();
    m_today.wendu = dataObj.value("wendu").toString().toInt();
    //qDebug() << dataObj;
    //qDebug() << mToday.shidu << mToday.quality << mToday.ganmao << mToday.pm25 << mToday.wendu;
    //注意:forecast中的第2个元素也是今天的数据
    m_today.type = m_day[1].type;
    qDebug()<<"今天的天气是: "<<m_today.type;
    m_today.low = m_day[1].low;
    m_today.high = m_day[1].high;
    m_today.fx = m_day[1].fx;
    m_today.fl = m_day[1].fl;
    //qDebug() << mToday.type << mToday.low << mToday.high << mToday.fx << mToday.fl;
    UpdateUi();

    //更新曲线在搜索城市完成后手动更新曲线
    ui->lblHighCurve->update();
    ui->lblLowCurve->update();
}

解析完JSON数据之后在更新ui(UpdateUi();)

7.更新UI

cpp 复制代码
void MainWindow::UpdateUi()
{
    ui->lblDate->setText(QDateTime::fromString(m_today.date,"yyyyMMdd").toString("yyyy/MM/dd")+" "+m_day[1].week);
    ui->lblCity->setText(m_today.city);
    //更新今天数据
    ui->lblTypeIcon->setPixmap(m_typeMap[m_today.type]);//更新图片
    ui->lblTemp->setText(QString ::number(m_today.wendu));
    ui->lblType->setText(m_today.type);
    ui->lblLowHigh->setText(QString ::number(m_today.low)+"℃ ~ "+QString::number(m_today.high)+"℃");

    ui->lblGanMao->setText("感冒指数: "+m_today.ganmao);
    ui->lblWindFl->setText(m_today.fl);
    ui->lblWindFx->setText(m_today.fx);

    ui->lblPM25->setText(QString::number(m_today.pm25));
    ui->lblShiDu->setText(m_today.shidu);
    ui->lblQuality->setText(m_today.quality);
    //更新六天
    for(int i=0;i<6;i++){
        //更新日期和时间
        m_weekList[i]->setText("周"+m_day[i].week.right(1));//从右边取第一个
        ui->lblWeek0->setText("昨天");
         ui->lblWeek1->setText("今天");
         ui->lblWeek2->setText("明天");

//         //把日期提取出来变成 10/10格式
         QStringList slist=m_day[i].ymd.split("-");
         qDebug()<<slist;
         m_dateList[i]->setText(slist.at(1)+"/"+slist.at(2));

         //更新天气类型
         m_typeList[i]->setText(m_day[i].type);
         m_typeIconList[i]->setPixmap(m_typeMap[m_day[i].type]);//更新图片
//空气质量
        switch (checkedQulity(m_day[i].aqi)) {
        case 1:
            m_ApiList[i]->setText("优");
            m_ApiList[i]->setStyleSheet("background-color: rgb(121,184,0);");
            break;
        case 2:
            m_ApiList[i]->setText("良");
            m_ApiList[i]->setStyleSheet("background-color: rgb(255,187,23);");
            break;
        case 3:
            m_ApiList[i]->setText("轻度");
            m_ApiList[i]->setStyleSheet("background-color: rgb(255,87,97);");
            break;
        case 4:
            m_ApiList[i]->setText("中度");
            m_ApiList[i]->setStyleSheet("background-color: rgb(235,17,27);");
            break;
        case 5:
            m_ApiList[i]->setText("重度");
            m_ApiList[i]->setStyleSheet("background-color: rgb(170,0,0);");
            break;
        case 6:
            m_ApiList[i]->setText("严重");
            m_ApiList[i]->setStyleSheet("background-color: rgb(110,0,0);");
            break;
        }
        //风力风向
        m_FXList[i]->setText(m_day[i].fx);
        m_FLList[i]->setText(m_day[i].fl);
    }

}

//检查空气质量
int MainWindow::checkedQulity(int aqi)
{
    if (aqi >= 0 && aqi <= 50) {
         return 1;
    }else if(aqi > 50 && aqi <= 100){
         return 2;
    }else if(aqi > 100 && aqi <= 150){
         return 3;
    }else if(aqi > 150 && aqi <= 200){
         return 4;
    }else if(aqi > 200 && aqi <= 250){
         return 5;
    }else{
         return 6;
    }
    return -1;
}

8.实现搜索框搜索城市

获取LeCity搜索框输入的数据

cpp 复制代码
void MainWindow::on_btnSearch_clicked()
{
    QString cityName=ui->leCity->text();
    getWeaterInfo(cityName);
}

天气工具类

cpp 复制代码
//天气工具类
class weatherTool{
private:
    //内联静态变量 在占用调用处的内存
    inline static QMap<QString,QString> m_cityMap={};
    static void initCityMap(){
        QFile fd("E:\\code\\citycode.json");
        fd.open(QIODevice::ReadOnly|QIODevice::Text);
        QByteArray allJson=fd.readAll();
        fd.close();
        QJsonParseError err;
        //读出的数据转换为json的
        QJsonDocument doc=  QJsonDocument::fromJson(allJson,&err);

        if(err.error!=QJsonParseError::NoError||!doc.isArray()){
          //不是数组就错误
            qDebug()<<"json数据转换失败...";
            return;
      }  //转换成json数组
        QJsonArray rootArray=doc.array();
      for(int i=0;i<rootArray.size();i++){
            QString cityName = rootArray[i].toObject().value("city_name").toString();
            QString cityCode = rootArray[i].toObject().value("city_code").toString();
            //判断编号是否存在
            if(cityCode.size()>0){
                m_cityMap.insert(cityName,cityCode);
            }
        }

    }

public :
    QString static getCityCode(QString cityName){
        qDebug()<<"cityName"<<cityName;
        if(m_cityMap.isEmpty()){
            qDebug()<< m_cityMap.isEmpty();
            initCityMap();
        }
        if(cityName==""){
            QMessageBox::warning(nullptr,"错误(null)","输入的城市不能为空...",QMessageBox::Ok);
            return "";
        }
  //在map寻找传入的城市名称,返回值可以遍历
        //返回的是map中的多个元素
        QMap<QString, QString>::iterator it = m_cityMap.find(cityName);
        //到结尾了,未找到,加上市,再搜一遍
        if (it == m_cityMap.end()) {
           it = m_cityMap.find(cityName + "市");
        }
        //找到了
        if (it != m_cityMap.end()) {
           qDebug()<<" if (it != m_cityMap.end())";
           return it.value();
        }

        QMessageBox::warning(nullptr,"城市名字错误","输入的城市名字错误...",QMessageBox::Ok);
        //否则
        return "";
    }


};

读取这个文件里面的数据QFile fd("E:\\code\\citycode.json");把city_name和city_code取出来放到QMap集合里面去,之后在和输入的CityName进行查找获得city_code.

相关推荐
wjs202415 小时前
CSS 颜色
开发语言
无巧不成书021815 小时前
Java数值字面量速查表
java·开发语言·python·开发者·字面量
小鸡吃米…15 小时前
测试线程应用程序
开发语言·python
python开发笔记15 小时前
python(79) 底层代码追踪工具
开发语言·python
kgduu15 小时前
js之错误处理
开发语言·前端·javascript
Bert.Cai15 小时前
Python函数的定义与调用
开发语言·python
美式请加冰15 小时前
模拟的介绍和使用
java·开发语言·算法
无限进步_15 小时前
深入解析vector:一个完整的C++动态数组实现
c语言·开发语言·c++·windows·git·github·visual studio
万能的小裴同学15 小时前
C++ 简易的FBX查看工具
开发语言·c++·算法
菜菜小狗的学习笔记15 小时前
剑指Offer算法题(二)栈、队列、堆
java·开发语言