qt天气的获取

发布于:2025-07-21 ⋅ 阅读:(20) ⋅ 点赞:(0)

该系统实现了获取网站上的天气到本地进行展示的功能,代码如下所示:

mainwindos.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include"weatherData.h"
#include<QNetworkAccessManager>
#include<QAction>
#include<QMenu>
#include<QLineEdit>
#include<QPushButton>
#include<QDateTime>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

protected:
    void mousePressEvent(QMouseEvent *event) override;      //重写鼠标点击事件函数
    void mouseMoveEvent(QMouseEvent *event) override;       //重写鼠标移动事件函数

    void getWeatherInfo(QString citycode);                  //获取天气数据

    void parseJson(QByteArray& byteArray);                  //解析JSON数据

    void updateWeatherDisplay();
    void onSearchBtnClicked();
    void refreshWeather();
private slots:
    void on_pushButton_quit_clicked();          //关闭UI界面
    void onQuitActTriggered();                  //菜单被点击后的处理

public slots:
    void readHttpReply(QNetworkReply *reply);                       //新建一个网络请求获取的槽函数
QString getAirQualityColor(const QString& quality);
private:
    Ui::MainWindow *ui;
    QMenu *quitMenu;                            //创建一个菜单指针
    QAction *quitAct;                           //定义一个动作
    QPoint moffset;                             //窗口移动时,鼠标与窗口左上角的偏移值

    QTimer *refreshTimer;
    QNetworkAccessManager *NetAccessManger;        //声明一个网络请求对象

    bool closePOPWindow();                      //关闭窗口的弹窗

    Today today;                                //定义一个今天天气数据对象
    Day day[7];

    QDateTime lastRefreshTime;
    bool isRefreshing = false;
    QString currentCityCode;




};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QMouseEvent>
#include "weatherData.h"
#include<QMessageBox>
#include<QNetworkReply>
#include<QPushButton>
#include<QLineEdit>
#include<QTimer>
#include<QMessageBox>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowFlag(Qt::FramelessWindowHint);

    // 创建带有HTML格式的文本
    QString cityHtml = "<html><head><style>"
                      "body { font-family: 'Microsoft YaHei', sans-serif; margin: 0; }"
                      "h2 { color: #2c3e50; text-align: center; margin-bottom: 15px; }"
                      "table { width: 100%; border-collapse: collapse; }"
                      "th { background-color: #3498db; color: white; padding: 10px; text-align: left; }"
                      "td { padding: 8px 12px; border-bottom: 1px solid #ecf0f1; }"
                      "tr:nth-child(even) { background-color: #f9f9f9; }"
                      "tr:hover { background-color: #f1f9ff; }"
                      ".footer { margin-top: 15px; text-align: center; color: #7f8c8d; font-size: 12px; }"
                      "</style></head>"
                      "<body>"
                      "<h2>主要城市天气预报代码列表</h2>"
                      "<table>"
                      "<tr><th>城市</th><th>城市代码</th><th>城市</th><th>城市代码</th></tr>";

    // 城市数据对
    QVector<QPair<QString, QString>> cities = {
        {"北京", "101010100"}, {"上海", "101020100"}, {"天津", "101030100"}, {"重庆", "101040100"},
        {"哈尔滨", "101050101"}, {"长春", "101060101"}, {"沈阳", "101070101"}, {"呼和浩特", "101080101"},
        {"石家庄", "101090101"}, {"太原", "101100101"}, {"西安", "101110101"}, {"济南", "101120101"},
        {"郑州", "101180101"}, {"合肥", "101220101"}, {"南京", "101190101"}, {"杭州", "101210101"},
        {"福州", "101230101"}, {"南昌", "101240101"}, {"长沙", "101250101"}, {"武汉", "101200101"},
        {"广州", "101280101"}, {"南宁", "101300101"}, {"海口", "101310101"}, {"成都", "101270101"},
        {"贵阳", "101260101"}, {"昆明", "101290101"}, {"拉萨", "101140101"}, {"兰州", "101160101"},
        {"银川", "101170101"}, {"西宁", "101150101"}, {"乌鲁木齐", "101130101"}, {"台北", "101340101"},
        {"香港", "101320101"}, {"澳门", "101330101"}
    };

    // 组织城市数据到表格(两列布局)
    for (int i = 0; i < cities.size(); i += 2) {
        cityHtml += "<tr>";

        // 第一列城市
        cityHtml += QString("<td><b>%1</b></td><td>%2</td>")
                   .arg(cities[i].first).arg(cities[i].second);

        // 第二列城市(如果存在)
        if (i + 1 < cities.size()) {
            cityHtml += QString("<td><b>%1</b></td><td>%2</td>")
                       .arg(cities[i+1].first).arg(cities[i+1].second);
        } else {
            cityHtml += "<td></td><td></td>"; // 空单元格保持对齐
        }

        cityHtml += "</tr>";
    }

    cityHtml += "</table>"
               "<div class='footer'>数据更新于: " + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm") + "</div>"
               "</body></html>";

    // 设置HTML格式文本
    ui->textEdit->setHtml(cityHtml);
    //每隔三分钟自动刷新一下天气情况
    refreshTimer = new QTimer(this);
    refreshTimer->setInterval(180000); // 3分钟 = 180,000毫秒

    // 连接定时器信号
    connect(refreshTimer, &QTimer::timeout, this, [=]() {
        refreshWeather();
       });

    // 启动定时器
    refreshTimer->start();

    //ui->cityInput->setGeometry(50, 10, 200, 30);
    ui->cityInput->setPlaceholderText("输入城市代码 (如:101010100)");
    ui->cityInput->setStyleSheet("QLineEdit { background-color: white; border: 1px solid #ccc; border-radius: 5px; padding: 5px; }");

    // 查询按钮

    //ui->btn_search->setGeometry(260, 10, 80, 30);
    ui->btn_search->setText("查询");
    ui->btn_search->setStyleSheet("QPushButton { background-color: #4CAF50; color: white; border-radius: 5px; font-size: 14px;}");

    //ui->weatherDisplay->setGeometry(50, 50, 300, 30); // 设置位置和大小
    ui->weatherDisplay->setReadOnly(true); // 设置为只读
    ui->weatherDisplay->setStyleSheet("QLineEdit {"
                                     "background-color: #f0f0f0;"
                                     "border: 1px solid #ccc;"
                                     "border-radius: 5px;"
                                     "padding: 5px;"
                                     "font-size: 14px;"
                                     "}");

    // 显示加载状态信息
    ui->weatherDisplay->setText("正在获取天气信息,请稍候...");

//    QPushButton*btn=new QPushButton(this);
//    btn->setText("测试");
    //    this->setLayout(ui->gridLayoutGlobal);      //让界面随着窗口变幻大小

    quitMenu = new QMenu(this);         //创建一个QMenu对象
    quitAct = new QAction(QIcon(":/widget/quit.png"), tr("退出"), this);     //定义一个退出动作
    quitMenu->addAction(quitAct);       //添加动作

    //    connect(quitMenu,&QMenu::triggered,this,[=]{
    //        this->close();
    //    });         //连接信号与槽

    connect(quitMenu,&QMenu::triggered,this,&MainWindow::onQuitActTriggered);   //连接菜单被触发的信号与槽

    NetAccessManger = new QNetworkAccessManager(this);          //实例化一个网络请求对象

    connect(NetAccessManger,&QNetworkAccessManager::finished,this,&MainWindow::readHttpReply);  //连接网络请求获取的信号与槽

    //101010100是北京的城市编码
    //getWeatherInfo("101010100");

    connect(ui->btn_search, &QPushButton::clicked, this, &MainWindow::onSearchBtnClicked);

}

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

//鼠标点击
void MainWindow::mousePressEvent(QMouseEvent *event)
{
    //如果右键被按下
    if(event->button() == Qt::RightButton)
    {
        quitMenu->exec(QCursor::pos());       //在当前鼠标位置显示菜单
    }

    //当前鼠标位置 event->globalPos()
    //当前窗口位置 this->pos()
    if(event->button() == Qt::LeftButton)
    {
        moffset = event->globalPos() - this->pos();
    }
}

//鼠标移动
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    this->move(event->globalPos() - moffset);    //移动窗口
}


//弹窗
bool MainWindow::closePOPWindow()
{
    // 创建一个消息框询问用户是否真的要退出
    QMessageBox mes;
    mes.setWindowTitle("关闭窗口");
    //  mes.setWindowFlags(Qt::Drawer);       //把标题栏去掉
    mes.setIcon(QMessageBox::Warning);    //设置一个警告图片
    mes.setText("是否关闭窗口?");          //弹窗文本

    mes.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);     //设置两个按钮
    mes.setWindowIcon(QIcon(":/widget/dog.png")); // 设置窗口图标
    mes.setButtonText(QMessageBox::Ok, tr("确定"));               //ok改为确认
    mes.setButtonText(QMessageBox::Cancel, tr("取消"));           //Cancel改为取消

    // 显示消息框并等待用户交互
    int result = mes.exec();

    // 根据用户的选择执行相应的操作
    if (result == QMessageBox::Ok) {
        // 用户选择了确定,关闭主窗口
        this->close();
        return true;
    }
    // 用户选择了取消,不关闭主窗口
    else
    {
        return false;     // 窗口关闭操作失败
    }
}

//右上角退出
void MainWindow::on_pushButton_quit_clicked()
{
    closePOPWindow();
}

//鼠标右键退出
void MainWindow::onQuitActTriggered()
{
    closePOPWindow();
}


//获取天气数据
void MainWindow::getWeatherInfo(QString citycode)
{
    QUrl url("http://t.weather.itboy.net/api/weather/city/" + citycode);     //天气数据接口和城市编码
    NetAccessManger->get(QNetworkRequest(url));                    //发送GET请求,获取数据

}

//解析JSON格式天气数据
void MainWindow::parseJson(QByteArray &byteArray)
{
    //错误
    QJsonParseError err;        //创建一个错误对象
    QJsonDocument doc = QJsonDocument::fromJson(byteArray, &err);   //将JSON格式解析为QJsonDocument对象
    //如果错误
    if(err.error != QJsonParseError::NoError)
    {
        return;    //返回
    }

    QJsonObject rootObj = doc.object();     //创建一个QJsonObject对象返回文档
    //    qDebug() << rootObj.value("message").toString();

    //1.解析城市和日期
    today.city = rootObj.value("cityInfo").toObject().value("city").toString();     //城市
    today.date = rootObj.value("date").toString();                                  //日期

    //2.解析昨天yesterday数据
    QJsonObject objData = rootObj.value("data").toObject();         //获取data对象

    QJsonObject objYesterday = objData.value("yesterday").toObject();          //昨天
    day[0].week = objYesterday.value("week").toString();                       //星期
    day[0].date = objYesterday.value("date").toString();                       //日期

    day[0].weatherType = objYesterday.value("type").toString();                      //天气类型

    QString highT;          //最高温
    highT = objYesterday.value("high").toString().split(" ").at(1); //空格分割,取分割后第二个数据,1是第二个,0是第一个
    day[0].highTem = highT.left(highT.length() - 1).toInt(); //把℃减掉,只剩数字
    QString lowT;           //最低温
    lowT = objYesterday.value("low").toString().split(" ").at(1);
    day[0].lowTem = lowT.left(lowT.length() - 1).toInt();

    //风的类型,风力
    day[0].windType = objYesterday.value("fx").toString();      //风的类型
    day[0].windPower = objYesterday.value("fl").toString();     //风力

    //空气指数
    day[0].airQuality =objYesterday.value("aqi").toDouble();    //空气质量

    //3.解析未来几天的天气数据
    QJsonArray forecastArray = objData.value("forecast").toArray();        //获取forecast数组
    //遍历未来几天天气数据
    for(int i=0 ; i<6 ; i++)
    {
        QJsonObject forecastObj = forecastArray[i].toObject();             //获取JSON对象

        day[i+1].week = forecastObj.value("week").toString();             //星期
        day[i+1].date = forecastObj.value("ymd").toString();              //日期
        day[i+1].weatherType = forecastObj.value("type").toString();      //天气类型
        //空气指数
        day[i+1].airQuality =forecastObj.value("aqi").toDouble();         //空气质量


        QString highT;      //最高温
        highT = forecastObj.value("high").toString().split(" ").at(1);      //空格分割,取分割后第二个数据,1是第二个,0是第一个
        day[i+1].highTem = highT.left(highT.length() - 1).toInt();          //把℃减掉,只剩数字
        QString lowS;       //最低温
        lowS = forecastObj.value("low").toString().split(" ").at(1);
        day[i+1].lowTem = lowS.left(lowS.length() - 1).toInt();

        //风的类型,风力
        day[i+1].windType = forecastObj.value("fx").toString();           //风的类型
        day[i+1].windPower = forecastObj.value("fl").toString();          //风力

        //4、解析今天的数据
        today.Temperature =objData.value("wendu").toInt();                 //温度

        today.ganMao =objData.value("ganmao").toString();                  //感冒指数

        today.Humidity = objData.value("shidu").toString();                //湿度
        today.PM25 = objData.value("pm25").toDouble();                        //PM2.5
        today.airQuality = objData.value("quality").toString();            //空气质量

        //5、forecast里面也有今天的数据
        today.weatherType = day[1].weatherType;                            //天气类型
        today.highTem = day[1].highTem;                                    //最高温
        today.lowTem = day[1].lowTem;                                      //最低温

        today.windType = day[1].windType;                                  //风的类型
        today.windPower = day[1].windPower;   //风力

    }
    updateWeatherDisplay();
}

//网络请求获取
void MainWindow::readHttpReply(QNetworkReply *reply)
{
    int status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();   //状态码

    //请求错误
    if(reply->error() != QNetworkReply::NoError || status_code != 200)
    {
        qDebug() << reply->errorString().toLatin1().data();     //打印错误信息
        QMessageBox::warning(this,"天气","请求数据失败", QMessageBox::Ok);      //弹出警告信息框
    }
    //请求成功
    else
    {
        QByteArray byteArray = reply->readAll();        //读取服务器数据
        qDebug() << "read all:"<< byteArray.data();     //打印接收到的数据
        parseJson(byteArray);                           //解析JSON数据
    }
    reply->deleteLater();       //释放对象
}

void MainWindow::updateWeatherDisplay()
{
    QDateTime nextRefresh = lastRefreshTime.addMSecs(refreshTimer->interval());



    QString weatherInfo = QString(
            "🌆 %1  |  🕒 %2更新  |  🌡️ %3℃  |  ☁️ %4  |  "
            "⬇️ %5℃  |  ⬆️ %6℃  |  💨 %7  |  "
            "🍃 %8"
        )
        .arg(today.city)
        .arg(lastRefreshTime.toString("hh:mm"))
        .arg(today.Temperature)
        .arg(today.weatherType)
        .arg(today.lowTem)
        .arg(today.highTem)
        .arg(today.windPower)
        .arg(today.airQuality);

        // 设置文本
        ui->weatherDisplay->setText(weatherInfo);

        // 设置样式表 - 根据空气质量变化背景色
        QString style = "QLineEdit {"
                        "background-color: %1;"
                        "border: 2px solid #3498db;"
                        "border-radius: 15px;"
                        "padding: 10px 15px;"
                        "font-size: 14px;"
                        "font-weight: bold;"
                        "color: #2c3e50;"
                        "}";

        if (today.airQuality == "优") {
            ui->weatherDisplay->setStyleSheet(style.arg("#d5f5e3")); // 浅绿色
        } else if (today.airQuality == "良") {
            ui->weatherDisplay->setStyleSheet(style.arg("#fef9e7")); // 浅黄色
        } else if (today.airQuality == "轻度污染") {
            ui->weatherDisplay->setStyleSheet(style.arg("#fdebd0")); // 浅橙色
        } else {
            ui->weatherDisplay->setStyleSheet(style.arg("#fadbd8")); // 浅红色
        }

        // 添加提示文本
        ui->weatherDisplay->setPlaceholderText("输入城市代码查询天气");

        // 设置对齐方式
        ui->weatherDisplay->setAlignment(Qt::AlignCenter);

        // 添加悬停效果
        ui->weatherDisplay->setStyleSheet(ui->weatherDisplay->styleSheet() +
            "QLineEdit:hover {"
            "   background-color: #eaf2f8;"
            "   border: 2px solid #2980b9;"
            "}");

        // 添加焦点效果
        ui->weatherDisplay->setStyleSheet(ui->weatherDisplay->styleSheet() +
            "QLineEdit:focus {"
            "   background-color: #ffffff;"
            "   border: 2px solid #3498db;"
            "}");
}
void MainWindow::refreshWeather()
{
    // 如果正在刷新,则跳过
        if (isRefreshing) {
            return;
        }

        isRefreshing = true;

        // 显示刷新状态
        ui->weatherDisplay->setText("正在刷新天气数据...");

        // 记录刷新时间
        lastRefreshTime = QDateTime::currentDateTime();

        // 获取天气信息
        getWeatherInfo(currentCityCode);

        // 在 readHttpReply 中重置刷新状态
}
void MainWindow::onSearchBtnClicked()
{

       getWeatherInfo(ui->cityInput->text());
}

QString MainWindow::getAirQualityColor(const QString& quality)
{
    if (quality == "优") {
        return "#2ecc71"; // 绿色
    } else if (quality == "良") {
        return "#f1c40f"; // 黄色
    } else if (quality == "轻度污染") {
        return "#e67e22"; // 橙色
    } else if (quality == "中度污染" || quality == "重度污染" || quality == "严重污染") {
        return "#e74c3c"; // 红色
    } else {
        return "#95a5a6"; // 默认灰色
    }
}
weatherData.h
#ifndef WEATHERDATA_H
#define WEATHERDATA_H
#include <QString>
//今天的数据类
class Today{
public:
    Today()
    {
        city ="广州";     //城市
        date ="2025-1-10";  //日期


        weatherType ="多云";     //天气类型
        highTem = 30;           //最高温
        lowTem = 18;            //最低温

        ganMao ="感冒指数";      //感冒指数

        Temperature = 0;       //温度
        Humidity = "0%";       //湿度
        PM25 = 0;              //PM2.5
        windType ="南风";       //风的类型
        windPower ="2级";       //风力
        airQuality ="无数据";    //空气质量
    }
public:

    QString city;
    QString date;

    int Temperature;
    QString weatherType;

    int highTem;
    int lowTem;

    QString ganMao;

    QString Humidity;
    int PM25;
    QString windType;
    QString windPower;
    QString airQuality;

};

//未来几天的数据类
class Day{
public:
    Day()
    {
        week ="周五";             //星期
        date ="2023-7-29";       //日期

        weatherType ="多云";      //天气类型

        airQuality = 0; //空气指数,优        //空气质量

        highTem = 0;              //最高温
        lowTem = 0;               //最低温

        windType ="南风";          //风的类型
        windPower ="2级";         //风力
    }

    QString week;
    QString date;

    QString weatherType;

    int airQuality;

    int highTem;
    int lowTem;

    QString windType;
    QString windPower;
};
#endif // WEATHERDATA_H
main.cpp
#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}