【QT篇】天气预报

一、功能概述

1.功能介绍

•支持按照城市名查找当地天气

•支持显示未来7天天气状况

•支持显示穿衣建议

2.界面预览

二、常用类

在此主要罗列一些主要使用的类,具体请查阅QT帮助手册

•QMenu
•QAction
•QNetworkAccessManager
•QNetworkRequest
•QNetworkReply
•QJsonDocument
•QJsonObject
•QJsonArray
•QMap

三、项目源码

https://gitee.com/GeekerGao/weather-forecast

部分代码

#include "widget.h"
#include "ui_widget.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QMessageBox>
#include <QMouseEvent>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setFont(QFont("Arial",15));
    setFixedSize(593,956);
    setWindowFlag(Qt::FramelessWindowHint);
    //新建一个菜单组件
    menuQuit = new QMenu(this);
    //设置菜单项文字颜色
    menuQuit->setStyleSheet("QMenu::item{color:white}");
    //为菜单组件添加一个动作
    QAction *closeAct = new QAction(QIcon(":/new/prefix1/res/close.png"),tr("退出"),this);
    menuQuit->addAction(closeAct);
    //用户选择菜单项并点击后回调函数,退出程序
    connect(menuQuit,&QMenu::triggered,this,[=]{
        this->close();
    });
    //由QNetworkAccessManager发起get请求
    manager = new QNetworkAccessManager(this);
    strUrl = "http://v1.yiketianqi.com/api?unescape=1&version=v9&appid=47546632&appsecret=bOHHPCP1";
    QUrl urlTianQi(strUrl);
    //指定请求的url地址
    QNetworkRequest res(urlTianQi);
    reply = manager->get(res);
    //QNetworkRequest网络请求后进行数据读取
    connect(manager,&QNetworkAccessManager::finished,this,&Widget::readHttpReply);

    mDayList << ui->labelday0 << ui->labelday1
             << ui->labelday2 << ui->labelday3
             << ui->labelday4 << ui->labelday5;
    mDateList << ui->labeldate0 << ui->labeldate1
              << ui->labeldate2 << ui->labeldate3
              << ui->labeldate4 << ui->labeldate5;
    mIconList << ui->labelWeatherIcon0 << ui->labelWeatherIcon1
              << ui->labelWeatherIcon2 << ui->labelWeatherIcon3
              << ui->labelWeatherIcon4 << ui->labelWeatherIcon5;
    mWeaTypeList << ui->labelWeatherTypeDate0 << ui->labelWeatherTypeDate1
                 << ui->labelWeatherTypeDate2 << ui->labelWeatherTypeDate3
                 << ui->labelWeatherTypeDate4 << ui->labelWeatherTypeDate5;
    mAiqList << ui->labelaiq0 << ui->labelaiq1
             << ui->labelaiq2 << ui->labelaiq3
             << ui->labelaiq4 << ui->labelaiq5;
    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("暴雪",":/new/prefix1/res/type/BaoXue.png");
    mTypeMap.insert("暴雨",":/new/prefix1/res/type/BaoYu. png");
    mTypeMap.insert("暴雨到大暴雨",":/new/prefix1/res/type/BaoYuDaoDaBaoYu.png");
    mTypeMap.insert("大暴雨",":/new/prefix1/res/type/DaBaoYu.png");
    mTypeMap.insert("大暴雨到特大暴雨",":/new/prefix1/res/type/DaBaoYuDaoTeDaBaoYu.png");
    mTypeMap.insert("大到暴雪",":/new/prefix1/res/type/DaDaoBaoXue.png");
    mTypeMap.insert("大雪",":/new/prefix1/res/type/DaXue.png");
    mTypeMap.insert("大雨",":/new/prefix1/res/type/DaYu.png");
    mTypeMap.insert("冻雨",":/new/prefix1/res/type/DongYu.png");
    mTypeMap.insert("多云",":/new/prefix1/res/type/DuoYun.png");
    mTypeMap.insert("浮沉",":/new/prefix1/res/type/FuChen.png");
    mTypeMap.insert("雷阵雨",":/new/prefix1/res/type/LeiZhenYu.png");
    mTypeMap.insert("雷阵雨伴有冰雹",":/new/prefix1/res/type/LeiZhenYuBanYouBingBao.png");
    mTypeMap.insert("霾",":/new/prefix1/res/type/Mai.png");
    mTypeMap.insert("强沙尘暴",":/new/prefix1/res/type/QiangShaChenBao.png");
    mTypeMap.insert("晴",":/new/prefix1/res/type/Qing.png");
    mTypeMap.insert("沙尘暴",":/new/prefix1/res/type/ShaChenBao.png");
    mTypeMap.insert("特大暴雨",":/new/prefix1/res/type/TeDaBaoYu.png");
    mTypeMap.insert("undefined",":/new/prefix1/res/type/undefined.png");
    mTypeMap.insert("雾",":/new/prefix1/res/type/Wu.png");
    mTypeMap.insert("小到中雪",":/new/prefix1/res/type/XiaoDaoZhongXue.png");
    mTypeMap.insert("小到中雨",":/new/prefix1/res/type/XiaoDaoZhongYu.png");
    mTypeMap.insert("小雪",":/new/prefix1/res/type/XiaoXue.png");
    mTypeMap.insert("小雨",":/new/prefix1/res/type/XiaoYu.png");
    mTypeMap.insert("雪",":/new/prefix1/res/type/Xue.png");
    mTypeMap.insert("扬沙",":/new/prefix1/res/type/YangSha.png");
    mTypeMap.insert("阴",":/new/prefix1/res/type/Yin.png");
    mTypeMap.insert("雨",":/new/prefix1/res/type/Yu.png");
    mTypeMap.insert("雨夹雪",":/new/prefix1/res/type/YuJiaXue.png");
    mTypeMap.insert("阵雪",":/new/prefix1/res/type/ZhenXue.png");
    mTypeMap.insert("阵雨",":/new/prefix1/res/type/ZhenYu.png");
    mTypeMap.insert("中到大雪",":/new/prefix1/res/type/ZhongDaoDaXue.png");
    mTypeMap.insert("中到大雨",":/new/prefix1/res/type/ZhongDaoDaYu.png");
    mTypeMap.insert("中雪",":/new/prefix1/res/type/ZhongXue.png");
    mTypeMap.insert("中雨",":/new/prefix1/res/type/ZhongYu.png");

    ui->widget0404->installEventFilter(this);
    ui->widget0405->installEventFilter(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::RightButton){
        menuQuit->exec(QCursor::pos());
    }
    //鼠标当前位置event.globalPos();
    //窗口当前位置this.pos()
    //窗口新位置event->globalPos() - mOffset
    if(event->button() == Qt::LeftButton){
        mOffset = event->globalPos() - this->pos();
    }
}
//鼠标左键按下后的移动,导致这个事件被调用,设置窗口新位置
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){
        drawTempLineHigh();
        return true;//表示事件已被处理
    }
    if(watched == ui->widget0405 && event->type() == QEvent::Paint){
        drawTempLineLow();
        return true;//表示事件已被处理
    }
    return QWidget::eventFilter(watched, event);
}

//解析天气Json数据
void Widget:: parseWeatherJsonData(QByteArray rawData)
{
    QJsonDocument jsonObj = QJsonDocument::fromJson(rawData);
    if(!jsonObj.isNull() && jsonObj.isObject()){
        QJsonObject objRoot = jsonObj.object();
        //解析日期
        QString date = objRoot["date"].toString();
        QString week = objRoot["week"].toString();
        ui->labelCurrentDate->setText(date+"  "+week);
        //解析城市名
        QString cityName = objRoot["city"].toString();
        ui->labelCity->setText(cityName+"市");
        //解析当前温度
        QString currentTmp = objRoot["tem"].toString();
        ui->labelTemp->setText(currentTmp+"℃");
        ui->labelTempRange->setText(objRoot["tem2"].toString()+"℃"+"~"+
                                    objRoot["tem1"].toString()+"℃");
        //解析天气类型
        ui->labelWeatherType->setText(objRoot["wea"].toString());
        ui->labelWeatherIcon->setPixmap(mTypeMap[objRoot["wea"].toString()]);
        //感冒指数
        ui->labelGanMao->setText(objRoot["air_tips"].toString());
        //解析风向
        ui->labelFXType->setText(objRoot["win"].toString());
        //解析风力
        ui->labelFXData->setText(objRoot["win_speed"].toString());
        //解析PM2.5
        ui->labelPM25Data->setText(objRoot["air_pm25"].toString());
        //解析湿度
        ui->labelShiduData->setText(objRoot["humidity"].toString());
        //解析空气质量
        ui->labelAirData->setText(objRoot["air_level"].toString());
    }
}
//解析7天天气Json数据
void Widget::parseWeatherJsonDataNew(QByteArray rawData)
{
    QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData);
    if(!jsonDoc.isNull() && jsonDoc.isObject()){
        QJsonObject jsonRoot = jsonDoc.object();
        days[0].mCity = jsonRoot["city"].toString();
        days[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();
                days[i].mDate = obj["date"].toString();
                days[i].mWeek = obj["week"].toString();
                days[i].mWeaType = obj["wea"].toString();
                days[i].mTemp = obj["tem"].toString();
                days[i].mTempLow = obj["tem2"].toString();
                days[i].mTempHigh = obj["tem1"].toString();
                days[i].mFx = obj["win"].toArray()[0].toString();
                days[i].mFl = obj["win_speed"].toString();
                days[i].mAirq = obj["air_level"].toString();
                days[i].mTips = obj["index"].toArray()[3].toObject()["desc"].toString();
                days[i].mHu = obj["humidity"].toString();
            }
        }
    }
    updateUI();
}

void Widget::updateUI()
{
    QPixmap pixmap;
    //解析日期
    ui->labelCurrentDate->setText(days[0].mDate+"  "+days[0].mWeek);
    //解析城市名
    ui->labelCity->setText(days[0].mCity+"市");
    //解析当前温度
    ui->labelTemp->setText(days[0].mTemp+"℃");
    ui->labelTempRange->setText(days[0].mTempLow+"℃"+"~"+
                                days[0].mTempHigh+"℃");
    //解析天气类型
    ui->labelWeatherType->setText(days[0].mWeaType);
    ui->labelWeatherIcon->setPixmap(mTypeMap[days[0].mWeaType]);
    //感冒指数
    ui->labelGanMao->setText(days[0].mTips);
    //解析风向
    ui->labelFXType->setText(days[0].mFx);
    //解析风力
    ui->labelFXData->setText(days[0].mFl);
    //解析PM2.5
    ui->labelPM25Data->setText(days[0].mpm25);
    //解析湿度
    ui->labelShiduData->setText(days[0].mHu);
    //解析空气质量
    ui->labelAirData->setText(days[0].mAirq);
    //解析未来几天天气
    for(int i=0;i<6;i++){

        mDayList[i]->setText(days[i].mWeek);
        mDayList[0]->setText("今天");
        mDayList[1]->setText("明天");
        mDayList[2]->setText("后天");

        QStringList dayList = days[i].mDate.split("-");
        mDateList[i]->setText(dayList.at(1)+"-"+dayList.at(2));

        //缩放图片大小和label匹配
        int index = days[i].mWeaType.indexOf("转");
        if(index != -1){
            pixmap = mTypeMap[days[i].mWeaType.left(index)];
        }else{
            pixmap = mTypeMap[days[i].mWeaType];
        }
        pixmap = pixmap.scaled(mIconList[i]->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation);

        mIconList[i]->setMaximumHeight(50);
        mIconList[i]->setMaximumWidth(ui->widget0402->width()/6.5);
        mIconList[i]->setPixmap(pixmap);
        mWeaTypeList[i]->setText(days[i].mWeaType);

        QString airQ = days[i].mAirq;
        mAiqList[i]->setText(airQ);
        if(airQ == "优"){
            mAiqList[i]->setStyleSheet("background-color:rgb(150,213,32);border-radius:7px;color:rgb(230,230,230)");
        }
        if(airQ == "良"){
            mAiqList[i]->setStyleSheet("background-color:rgb(208,107,39);border-radius:7px;color:rgb(230,230,230)");
        }
        if(airQ == "轻度"){
            mAiqList[i]->setStyleSheet("background-color:rgb(255,199,199);border-radius:7px;color:rgb(230,230,230)");
        }
        if(airQ == "中度"){
            mAiqList[i]->setStyleSheet("background-color:rgb(255,17,17);border-radius:7px;color:rgb(230,230,230)");
        }
        if(airQ == "重度"){
            mAiqList[i]->setStyleSheet("backgroud-color:rgb(153,0,0);border-radius:7px;color:rgb(230,230,230)");
        }

        mFxList[i]->setText(days[i].mFx);
        index = days[i].mFl.indexOf("转");
        if(index != -1){
            mFlList[i]->setText(days[i].mFl.left(index));
        }else{
            mFlList[i]->setText(days[i].mFl);
        }
    }
    update();
}

void Widget::drawTempLineHigh()
{
    QPainter painter(ui->widget0404);
    painter.setRenderHint(QPainter::Antialiasing,true);
    painter.setBrush(Qt::yellow);
    painter.setPen(Qt::yellow);

    int ave;
    int sum = 0;
    int offSet = 0;
    int middle = ui->widget0404->height()/2;
    for(int i=0;i<6;i++){
        sum += days[i].mTempHigh.toInt();
    }
    ave = sum / 6;
    //定义出6个点
    QPoint points[6];
    for(int i=0;i<6;i++){
        points[i].setX(mAiqList[i]->x()+mAiqList[i]->width()/2);
        offSet = (days[i].mTempHigh.toInt() - ave) * 3;
        points[i].setY(middle - offSet);
        //画出6个点
        painter.drawEllipse(QPoint(points[i]),3,3);
        //画出当天温度
        painter.drawText(points[i].x()-15,points[i].y()-13,days[i].mTempHigh+"°");
    }
    for(int i=0;i<5;i++){
        painter.drawLine(points[i],points[i+1]);
    }
}

void Widget::drawTempLineLow()
{
    QPainter painter(ui->widget0405);
    painter.setRenderHint(QPainter::Antialiasing,true);
    painter.setBrush(QColor(70,192,203));
    painter.setPen(QColor(70,192,203));

    int ave;
    int sum = 0;
    int offSet = 0;
    int middle = ui->widget0404->height()/2;
    for(int i=0;i<6;i++){
        sum += days[i].mTempLow.toInt();
    }
    ave = sum / 6;
    //定义出6个点
    QPoint points[6];
    for(int i=0;i<6;i++){
        points[i].setX(mAiqList[i]->x()+mAiqList[i]->width()/2);
        offSet = (days[i].mTempLow.toInt() - ave) * 3;
        points[i].setY(middle - offSet);
        //画出6个点
        painter.drawEllipse(QPoint(points[i]),3,3);
        //画出当天温度
        painter.drawText(points[i].x()-15,points[i].y()-13,days[i].mTempLow+"°");
    }
    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();
    if(reply->error() == QNetworkReply::NoError && resCode == 200){
        //大多数服务器返回的字符编码格式是UTF8
        QByteArray data = reply->readAll();
        //parseWeatherJsonData(data);
        parseWeatherJsonDataNew(data);
    }else{
        QMessageBox mes;
        mes.setWindowTitle("错误");
        mes.setText("网络请求失败");
        mes.setStyleSheet("QPushButton{color:red}");
        mes.setStandardButtons(QMessageBox::Ok);
        mes.exec();
    }
}

void Widget::on_pushButton_clicked()
{
    QString cityNameFromUser = ui->lineEditCity->text();
    QString cityCode = cityCodeUtils.getCityCodeFromName(cityNameFromUser);
    if(cityCode != NULL){
        strUrl += "&cityid=" + cityCode;
        manager->get(QNetworkRequest(QUrl(strUrl)));
    }else{
        QMessageBox mes;
        mes.setWindowTitle("错误");
        mes.setText("请输入正确的城市名");
        mes.setStyleSheet("QPushButton{color:red}");
        mes.setStandardButtons(QMessageBox::Ok);
        mes.exec();
    }
}

void Widget::on_lineEditCity_returnPressed()
{
    on_pushButton_clicked();
}
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿gao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值