QT学习——天气预报

目录

1.界面预览

2.窗口的设置

3.网络通信的架构 

3.1CS架构(客户端-服务端架构)

3.2BS架构(浏览器-服务端架构) 

3.3CS与BS的区别 

3.4HTTP概述 

3.5HTTP编程 

4.JSON

4.1QT生成JSON数据

 4.2QT解析JSON数据

 5.完整程序

5.1.1widget.h

5.1.2widget.cpp

5.2.1day.h

5.3.1cityname.h


1.界面预览

2.窗口的设置

设置无状态栏
setWindowFlag(Qt::FramelessWindowHint);
设置左键弹窗关闭
menuQuit = new QMenu(this);
QAction *closeAct = new QAction(QIcon(":/res/close.png"), tr("退出"), this);
    menuQuit->addAction(closeAct);
    connect(menuQuit,&QMenu::triggered,this,[=]{
    this->close();
});
void Widget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::RightButton){
    //qDebug() << "right Mouse clicked!";
    menuQuit->exec(QCursor::pos());
    }
}

 设置窗口移动

void Widget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::RightButton){
    实现的逻辑
    7.5 天气预报数据接口
    第一种:
    数据返回:
    //qDebug() << "right Mouse clicked!";
    menuQuit->exec(QCursor::pos());
    }
    //鼠标当前位置 event->globalPos();,
    //窗口当前位置 this->pos()窗口新位置event->globalPos() - mOffset
    if(event->button() == Qt::LeftButton){
    // qDebug() << event->globalPos() << this->pos();
    mOffset = event->globalPos()-this->pos();
    }
}
    //鼠标左键按下后的移动,导致这个事件被调用,设置窗口的新位置
void Widget::mouseMoveEvent(QMouseEvent *event)
{
    this->move(event->globalPos() - mOffset);
}

 网址:2023最新可用免费天气预报API接口(更新2023-3-23)_天气接口-CSDN博客

3.网络通信的架构 

在计算机网络和软件开发中, CS 架构( Client-Server Architecture ,客户端 - 服务器架构)和 BS 架构 (Browser-Server Architecture ,浏览器 - 服务器架构)是两种主要的应用程序架构。

3.1CS架构(客户端-服务端架构)

CS 架构是一种典型的两层结构,包括客户端和服务器两个部分。在这种架构中,客户端和服务器通过网络进行通信,每部分都有明确的职责。
客户端:
  • 用户界面通常在客户端呈现。
  • 可以是桌面应用程序、移动应用或专用软件。
  • 负责向服务器发送请求,接收和处理服务器响应。

服务端

  • 管理数据和业务逻辑。
  • 处理来自客户端的请求,并发送回响应。
  • 通常承载在远程系统上,如数据库服务器、应用服务器等。

特点

  • 需要为每种操作系统或平台单独开发客户端。
  • 高效的数据处理和响应能力。
  • 在客户端设备上占用资源(如内存和处理能力)。

3.2BS架构(浏览器-服务端架构) 

BS架构是一种基于Web的三层或多层架构,主要通过Web浏览器作为客户端访问服务器上的应用程序。 

 浏览器(客户端)

  • 使用标准Web浏览器(如ChromeFirefox等)作为客户端。
  • 无需安装额外的软件,使用HTMLCSSJavaScript显示内容。

服务端

  • CS架构中的服务器类似,处理业务逻辑和数据存储。
  • 通过Web服务(如HTTP服务器)提供页面和数据。

特点

  • 跨平台兼容性强,可以在任何支持Web浏览器的设备上运行。
  • 客户端无需安装专用软件,容易维护和更新。
  • 可能依赖网络性能,因为所有操作都在服务器上进行。

3.3CS与BS的区别 

  • 部署和维护:BS架构易于部署和维护,而CS架构通常需要在每个客户端单独安装和更新。
  • 性能:CS架构可以更有效地利用客户端的计算资源,适合高性能要求的应用。BS架构依赖于服务器 的性能和网络延迟。
  • 安全性:CS架构中,数据经常在客户端和服务器之间传输,可能需要更复杂的安全措施。BS架构 中,敏感数据主要存储在服务器端。

3.4HTTP概述 

HTTP(Hypertext Transfer Protocol)是一种用于传输超文本(如HTML)数据的应用层协议,用于在客户端和服务器之间传输信息。以下是HTTP的基本概念: 

请求和响应

  • HTTP遵循客户端-服务器模型,其中客户端发送HTTP请求,服务器响应该请求并返回所需的数据。

请求方法

  • HTTP定义了不同的请求方法,最常见的是GET(获取资源)、POST(提交数据)、PUT(更新资源)、DELETE(删除资源)等 

状态码

  • HTTP响应包含一个状态码,用于表示请求的处理结果。常见的状态码包括200(成功)、404(未找到)、500(服务器内部错误)等  

URL(统一资源定位符) 

  • URL用于标识互联网上的资源位置。HTTP请求中包含URL,指示客户端请求的资源。

安全性

  • HTTP本身是不安全的,数据以明文形式传输。为了增加安全性,通常会使用HTTPS(HTTP Secure),通过加密和认证机制保护数据的传输。

Cookie和Session 

  • HTTP使用Cookie来跟踪用户会话状态,服务器可以通过在响应中设置Cookie来在客户端存储信息。Session则是在服务器端存储用户会话信息的一种机制。

缓存

  • HTTP支持缓存机制,允许客户端和代理服务器缓存响应,以减少数据传输和提高性能。

3.5HTTP编程 

Qt 中的 HTTP 编程主要涉及使用 Qt 的网络模块来进行 HTTP 请求和处理 HTTP 响应。 Qt 提供了一系列类来处 理网络通信,其中最常用的类是 QNetworkAccessManager QNetworkRequest QNetworkReply 以 及相关的支持类。

 第一步包含必要的头文件

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

第二步实例化QNetworkAccessManager对象,用于发送HTTP请求并处理响应。

QNetworkAccessManager *manager = new QNetworkAccessManager(this);

 第三步使用QNetworkRequest对象创建HTTP请求,设置URL、请求方法、请求头等信息

QNetworkRequest request(QUrl("http://example.com/api"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

 第四步使用QNetworkAccessManager发送HTTP请求,并获取返回的QNetworkReply对象。

QNetworkReply *reply = manager->get(request);

 第五步连接QNetworkReply的信号来处理HTTP响应,包括读取响应数据、处理错误等

connect(reply, &QNetworkReply::finished, this, [reply]() {
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray responseData = reply->readAll();
        // 处理响应数据
    } else {
        // 处理错误
    }
    reply->deleteLater();
});

第六步释放资源

delete manager;

例子:

#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>

int main(int argc, char *argv[])
{
    // 创建Qt应用程序对象
    QCoreApplication a(argc, argv);
    
    // 创建网络访问管理器对象
    QNetworkAccessManager manager;

    // 创建HTTP请求对象,指定请求的URL
    QNetworkRequest request(QUrl("http://example.com"));

    // 发送HTTP GET请求
    QNetworkReply *reply = manager.get(request);

    // 处理HTTP响应
    QObject::connect(reply, &QNetworkReply::finished, [&]() {
        // 检查是否有错误发生
        if (reply->error()) {
            qDebug() << "Error:" << reply->errorString();
            return;
        }

        // 读取响应数据
        QString response = reply->readAll();
        qDebug() << "Response:" << response;

        // 释放reply对象
        reply->deleteLater();
    });

    // 运行Qt应用程序事件循环
    return a.exec();
}

4.JSON

 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它易于人阅读和编写,同时也易于 机器解析和生成。JSON是基于JavaScript的一个子集,尽管它是独立于语言的,且有多种语言支持。 JSON常用于网络应用程序中的数据传输,尤其是在Web应用程序中与后端服务器通信。

原因描述
易于阅读和编写
JSON 的结构简单、清晰,对人类来说易于阅读和编写。
轻量级数据格式
相较于 XML 等标记语言, JSON 更轻量,使用更少的符号,数据体积更小。
易于解析和生成
大多数编程语言都提供了解析和生成 JSON 的内置支持或库。
跨语言支持
JSON 是独立于语言的,被广泛支持和使用在多种编程语言中。
网络友好
JSON 格式适合 Web 环境,易于通过网络传输,是 Web API 的常用格式。
数据互操作性
作为一种标准化格式, JSON 提高了不同系统间的数据互操作性

4.1QT生成JSON数据

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QFile>
#include <QDebug>

// 创建一个JSON文件并写入数据
void createJsonFile() {
    // 创建一个JSON对象,包含键值对
    QJsonObject jsonObj;
    jsonObj["name"] = "John Doe";
    jsonObj["age"] = 30;
    jsonObj["email"] = "john.doe@example.com";

    // 创建一个JSON数组
    QJsonArray jsonArr;
    jsonArr.append("C++");
    jsonArr.append("Python");
    jsonArr.append("JavaScript");
    jsonArr.append(123);

    // 将数组添加到JSON对象
    jsonObj["languages"] = jsonArr;

    // 将JSON对象转换为JSON文档
    QJsonDocument jsonDoc(jsonObj);

    // 将JSON文档转换为字符串(可以选择压缩格式)
    QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Indented);

    // 将JSON数据写入文件
    QFile file("output.json");
    if (!file.open(QIODevice::WriteOnly)) {
        qDebug() << "Failed to open file for writing";
        return;
    }
    file.write(jsonData);
    file.close();

    qDebug() << "JSON data saved to output.json";
}

int main() 
{
    // 调用创建JSON文件的函数
    createJsonFile();

    return 0;
}

解释说明: 

  • 创建JSON对象:使用 QJsonObject 来构建JSON对象,并使用键值对填充数据。
  • 创建JSON数组:使用 QJsonArray 来创建一个数组,并添加元素。
  • 组合JSON结构:将JSON数组添加到JSON对象中。
  • 生成JSON文档:通过 QJsonDocument 来处理JSON数据,可以选择格式化(缩进)或压缩形式。
  • 保存到文件:创建 QFile 对象,打开文件,写入JSON数据,并关闭文件。

这个例子展示了Qt处理JSON的基础流程,包括创建、填充数据、转换为字符串,以及写入文件。 

#include "widget.h"
#include "ui_widget.h"
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 创建一个JSON对象并添加键值对
    QJsonObject rootObj;
    rootObj["cityid"] = "1010100";
    rootObj["date"] = "2024-01-23";
    rootObj["weather"] = "雨夹雪";
    rootObj["tmp"] = 3;

    // 创建一个JSON数组并添加元素
    QJsonArray jsonArray;
    jsonArray.append("data1");
    jsonArray.append("data2");
    jsonArray.append("data3");
    jsonArray.append(100);

    // 将数组添加到JSON对象
    rootObj["testArry"] = jsonArray;

    // 将JSON对象转换为JSON文档
    QJsonDocument jsonDoc(rootObj);

    // 将JSON文档转换为字节数组
    QByteArray jsonArry = jsonDoc.toJson();

    // 创建一个文件对象并写入JSON数据
    QFile file("D:/QT/test.json");
    if (!file.open(QIODevice::WriteOnly)) {
        // 打开文件失败,输出错误信息
        qDebug() << "Failed to open file for writing";
        return;
    }
    file.write(jsonArry);
    file.close();

    // 输出操作完成的消息
    qDebug() << "JSON data saved to D:/QT/test.json";
}

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

 4.2QT解析JSON数据

Qt 中解析 JSON 数据通常涉及到使用 QJsonDocument QJsonObject QJsonArray 类。这些类提供 了处理JSON 数据的必要工具,使您能够从 JSON 字符串中提取信息、遍历 JSON 对象或数组,并访问具体 的数据项。以下是一个基本的示例,展示了如何在Qt 中解析 JSON 字符串。 
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
void parseJson() {
    // JSON字符串
    /*
    R 是用于定义原始字符串字面量(Raw String Literal)的标记。
    在C++中,原始字符串字面量是一种方便的语法,
    用于创建包含多行文本和特殊字符的字符串,而无需转义。
    R"("chenlichen")"
    */
    QString testStr = "chenli\"c";
    QString jsonString = R"(
    {
        "name": "John Doe",
        "age": 30,
        "email": "john.doe@example.com",
        "skills": ["C++", "Python", "JavaScript"]
    }
)";
// 将JSON字符串转换为QJsonDocument
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());
// 检查JSON文档是否包含一个对象
if (!jsonDoc.isNull() && jsonDoc.isObject()) {
    // 获取JSON对象
    QJsonObject jsonObj = jsonDoc.object();
    // 访问对象的键值
    QString name = jsonObj["name"].toString();
    int age = jsonObj["age"].toInt();
    QString email = jsonObj["email"].toString();
    qDebug() << "Name:" << name;
    qDebug() << "Age:" << age;
    qDebug() << "Email:" << email;
    // 处理JSON数组
    if (jsonObj.contains("skills") && jsonObj["skills"].isArray()) {
        QJsonArray skillsArray = jsonObj["skills"].toArray();
        for (const QJsonValue &value : skillsArray) {
            qDebug() << "Skill:" << value.toString();
        }
    }
    } else {
        qDebug() << "Invalid JSON...";
    }
}
int main() 
{
    parseJson();
    return 0;
}

解释说明: 

  • 字符串转换为 QJsonDocument :使用 QJsonDocument::fromJson 方法将JSON字符串转换为
  • QJsonDocument 对象。
  • 提取 QJsonObject :如果 QJsonDocument 包含一个JSON对象,使用 object() 方法获取它。
  • 访问对象数据:使用键(如 "name" "age" )访问 QJsonObject 中的数据。
  • 处理数组:如果对象包含一个数组,使用 QJsonArray 来遍历数组中的元素。

 4.3将JSON数据解析到QMap中

 

#include <QJsonDocument>
#include <QJsonObject>
#include <QMap>
#include <QDebug>
void parseJsonToMap() {
    // JSON字符串
    QString jsonString = R"(
        {
            "name": "John Doe",
            "age": "30",
            "email": "john.doe@example.com"
        }
    )";
    // 将JSON字符串转换为QJsonDocument
    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());
    // 准备一个QMap来存储解析的数据
    QMap<QString, QString> dataMap;
    // 解析JSON对象并填充QMap
    if (!jsonDoc.isNull() && jsonDoc.isObject()) {
        QJsonObject jsonObj = jsonDoc.object();
        for (auto key : jsonObj.keys()) {
        dataMap[key] = jsonObj.value(key).toString();
        }
    } else {
        qDebug() << "Invalid JSON...";
    }
    // 打印QMap内容
    for (auto key : dataMap.keys()) {
        qDebug() << key << ":" << dataMap[key];
    }
}
int main() 
{
    parseJsonToMap();
    return 0;
}

解释说明:

  • JSON字符串创建 QJsonDocument :使用 QJsonDocument::fromJson 来解析JSON字符串。
  • 创建 QMap :定义一个 QMap<QString, QString> 来存储键值对。
  •  遍历JSON对象:使用 keys() 方法获取所有键,然后遍历这些键,将对应的值添加到 QMap 中。
  •  打印 QMap 内容:遍历 QMap 并打印键值对。

 5.完整程序

5.1.1widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QMenu>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QList>
#include <QLabel>

#include "cityname.h"
#include "day.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();   
public:
    QList<QLabel *> _WeekList;
    QList<QLabel *> _DateList;
    QList<QLabel *> _IconList;
    QList<QLabel *> _WeathList;
    QList<QLabel *> _AirqList;
    QList<QLabel *> _FLList;
    QList<QLabel *> _FXList;
protected:
    //检测鼠标点击事件
    void mousePressEvent(QMouseEvent *event) override;
    //检测鼠标点击窗口移动事件
    void mouseMoveEvent(QMouseEvent *event) override;
    //
    bool eventFilter(QObject *watched, QEvent *event) override;
private slots:
    //读取天气的数据
    void readHttpRply(QNetworkReply *reply);
    //搜索城市
    void on_pushButton_clicked();

    void on_lineEditsearch_returnPressed();

private:
    Ui::Widget *ui;

    QMenu *menuQuit;//退出界面
    QPoint moveDistance; //界面移动
    QNetworkAccessManager *manager;//网络请求
    CityName citynames;//城市名称
    QMap <QString, QString> mTypeMap;//天气图片
    day days[7];//7日天气数据

    //解析天气的Json数据
    void parseCurrentWeatherJsonData(QByteArray readWeatherBuf);
    //解析7日天气的Json数据
    void parseCurrentWeatherJsonDatanew(QByteArray readWeatherBuf);
    //数据更新
    void updataUI();
    //画高温曲线
    void drawTempLineHigh();
    //画低温曲线
    void drawTempLineLow();
};
#endif // WIDGET_H

5.1.2widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include <QMouseEvent>
#include <QDebug>
#include <QIcon>
#include <QAction>
#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);

    menuQuit = new QMenu(this);

    _WeekList << ui->labelday01 << ui->labelday02
              << ui->labelday03 << ui->labelday04
              << ui->labelday05 << ui->labelday06;
    _DateList << ui->labeldaydata01 << ui->labeldaydata02
              << ui->labeldaydata03 << ui->labeldaydata04
              << ui->labeldaydata05 << ui->labeldaydata06;
    _IconList << ui->labelweath01 << ui->labelweath02
              << ui->labelweath03 << ui->labelweath04
              << ui->labelweath05 << ui->labelweath06;
    _WeathList << ui->labelweathdata01 << ui->labelweathdata02
               << ui->labelweathdata03 << ui->labelweathdata04
               << ui->labelweathdata05 << ui->labelweathdata06;
    _AirqList << ui->labelairq01 << ui->labelairq02
              << ui->labelairq03 << ui->labelairq04
              << ui->labelairq05 << ui->labelairq06;
    _FXList   << ui->labelwind01 << ui->labelwind02
              << ui->labelwind03 << ui->labelwind04
              << ui->labelwind05 << ui->labelwind06;
    _FLList   << ui->labelwinddata01 << ui->labelwinddata02
              <<ui->labelwinddata03  <<ui->labelwinddata04
             <<ui->labelwinddata05  <<ui->labelwinddata06;
    setFixedSize(378,682);//锁定显示的大小
    setWindowFlag(Qt::FramelessWindowHint);//去除边框
    menuQuit->setStyleSheet("QMenu::item {color:red}");//设置单项菜单文字颜色
    //用户点击菜单后执行回调函数程序结束
    connect(menuQuit, &QMenu::triggered, this, [=](){//此信号在触发此菜单中的操作时发出。
        this->close();
    });

    manager = new QNetworkAccessManager(this);
    //QString url = "http://v1.yiketianqi.com/api?unescape=1&version=v61&appid=17212311&appsecret=wgJCYY4x";
    //QString url = "http://t.weather.itboy.net";
    QString url = "http://v1.yiketianqi.com/api?unescape=1&version=v9&appid=17212311&appsecret=wgJCYY4x";
    manager->get(QNetworkRequest(QUrl(url)));//发起get请求
    connect(manager, &QNetworkAccessManager::finished, this, &Widget::readHttpRply);//访问成功后执行回调函数读取天气的数据

    mTypeMap.insert("暴雪",":/pic/type/BaoXue.png");
    mTypeMap.insert("暴雨",":/pic/type/BaoYu. png");
    mTypeMap.insert("暴雨到大暴雨",":/pic/type/BaoYuDaoDaBaoYu.png");
    mTypeMap.insert("大暴雨",":/pic/type/DaBaoYu.png");
    mTypeMap.insert("大暴雨到特大暴雨",":/pic/type/DaBaoYuDaoTeDaBaoYu.png");
    mTypeMap.insert("大到暴雪",":/pic/type/DaDaoBaoXue.png");
    mTypeMap.insert("大雪",":/pic/type/DaXue.png");
    mTypeMap.insert("大雨",":/pic/type/DaYu.png");
    mTypeMap.insert("冻雨",":/pic/type/DongYu.png");
    mTypeMap.insert("多云",":/pic/type/DuoYun.png");
    mTypeMap.insert("浮沉",":/pic/type/FuChen.png");
    mTypeMap.insert("雷阵雨",":/pic/type/LeiZhenYu.png");
    mTypeMap.insert("雷阵雨伴有冰雹",":/pic/type/LeiZhenYuBanYouBingBao.png");
    mTypeMap.insert("霾",":/pic/type/Mai.png");
    mTypeMap.insert("强沙尘暴",":/pic/type/QiangShaChenBao.png");
    mTypeMap.insert("晴",":/pic/type/Qing.png");
    mTypeMap.insert("沙尘暴",":/pic/type/ShaChenBao.png");
    mTypeMap.insert("特大暴雨",":/pic/type/TeDaBaoYu.png");
    mTypeMap.insert("undefined",":/pic/type/undefined.png");
    mTypeMap.insert("雾",":/pic/type/Wu.png");
    mTypeMap.insert("小到中雪",":/pic/type/XiaoDaoZhongXue.png");
    mTypeMap.insert("小到中雨",":/pic/type/XiaoDaoZhongYu.png");
    mTypeMap.insert("小雪",":/pic/type/XiaoXue.png");
    mTypeMap.insert("小雨",":/pic/type/XiaoYu.png");
    mTypeMap.insert("雪",":/pic/type/Xue.png");
    mTypeMap.insert("扬沙",":/pic/type/YangSha.png");
    mTypeMap.insert("阴",":/pic/type/Yin.png");
    mTypeMap.insert("雨",":/pic/type/Yu.png");
    mTypeMap.insert("雨夹雪",":/pic/type/YuJiaXue.png");
    mTypeMap.insert("阵雪",":/pic/type/ZhenXue.png");
    mTypeMap.insert("阵雨",":/pic/type/ZhenYu.png");
    mTypeMap.insert("中到大雪",":/pic/type/ZhongDaoDaXue.png");
    mTypeMap.insert("中到大雨",":/pic/type/ZhongDaoDaYu.png");
    mTypeMap.insert("中雪",":/pic/type/ZhongXue.png");
    mTypeMap.insert("中雨",":/pic/type/ZhongYu.png");

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

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

//检测鼠标点击事件 窗口的关闭和移动
void Widget::mousePressEvent(QMouseEvent *event)
{
    //为菜单添加一个动作
    QAction *closeAct = new QAction(QIcon(":/pic/close.png"), tr("退出"), this);
    //鼠标右键按下
    if(event->button() == Qt::RightButton){
        menuQuit->clear();
        menuQuit->addAction(closeAct);//将获取的图片添加到menu中
        menuQuit->exec(QCursor::pos());//QCursor::pos()
    }
    //鼠标左键按下
    if(event->button() == Qt::LeftButton){
        moveDistance = event->globalPos() - this->pos();//鼠标相对于窗口的偏移值
    }
}

//检测鼠标点击窗口移动事件
void Widget::mouseMoveEvent(QMouseEvent *event)
{
    //event->globalPos() - moveDistance 新窗口位置的坐标
    this->move(event->globalPos() - moveDistance);//移动到新窗口位置
}

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->widget0404 && event->type() == QEvent::Paint){
        drawTempLineHigh();
    }
    if(watched == ui->widget0405 && event->type() == QEvent::Paint){
        drawTempLineLow();
    }
}

//解析天气的Json数据
void Widget::parseCurrentWeatherJsonData(QByteArray readWeatherBuf)
{
    //把QByteArray转成JSONDoc
    QJsonDocument jsonDoc = QJsonDocument::fromJson(readWeatherBuf);
    if(!jsonDoc.isNull() && jsonDoc.isObject()){
        QJsonObject jsonRoot = jsonDoc.object();//把JsonDoc转成JsonObj
        //解析日期和时间
        ui->labelweek->setText(jsonRoot["date"].toString() + "  " + jsonRoot["week"].toString());
        //解析城市
        ui->labelcurrentcity->setText(jsonRoot["city"].toString());
        //当前的温度
        ui->labelcurrenttemp->setText(jsonRoot["tem"].toString() + "℃");
        //温度的区间
        ui->labeltemp->setText(jsonRoot["tem2"].toString() + "~" + jsonRoot["tem1"].toString());
        //天气情况
        ui->labelweathtype->setText(jsonRoot["wea"].toString());
        //天气情况图片
        ui->labelpic->setPixmap(mTypeMap[jsonRoot["wea"].toString()]);
        //感冒系数
        ui->labelganmao->setText("感冒系数:" + jsonRoot["air_tips"].toString());
        //风的方向
        ui->labelwindtext->setText(jsonRoot["win"].toString());
        //风速
        ui->labelwinddata->setText(jsonRoot["win_speed"].toString());
        //pm2.5
        ui->labelPM25data->setText(jsonRoot["air_pm25"].toString());
        //湿度
        ui->labelshidudata->setText(jsonRoot["humidity"].toString());
        //空气质量
        ui->labelairdata->setText(jsonRoot["air_level"].toString());
    }
}

void Widget::parseCurrentWeatherJsonDatanew(QByteArray readWeatherBuf)
{
    QJsonDocument jsonDoc = QJsonDocument::fromJson(readWeatherBuf);//将原始数据QByteArray转换成QJsonDocument
    //QJsonDocument不为空并且是QJsonObject
    if(!jsonDoc.isNull() && jsonDoc.isObject()){
        QJsonObject jsonRoot = jsonDoc.object();//将原始数据QJsonDocument转换成QJsonObject
        days[0]._City = jsonRoot["city"].toString();
        days[0]._Pm25 = 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]._Date = obj["date"].toString();//保存一周天气的各种数据
                days[i]._Week = obj["week"].toString();
                days[i]._WeathType = obj["wea"].toString();
                days[i]._Temp = obj["tem"].toString();
                days[i]._TempLow = obj["tem2"].toString();
                days[i]._TempHigh = obj["tem1"].toString();
                days[i]._FX = obj["win"].toArray()[0].toString();
                days[i]._FL = obj["win_speed"].toString();
                days[i]._Airq = obj["air_level"].toString();
                days[i]._Tips = obj["index"].toArray()[0].toObject()["desc"].toString();
                days[i]._Hu = obj["humidity"].toString();
            }
        }
    }
    updataUI();
}

void Widget::updataUI()
{
    QPixmap pixMap;

    //解析日期
    ui->labelweek->setText(days[0]._Date + "  " + days[0]._Week);
    //解析城市
    ui->labelcurrentcity->setText(days[0]._City);
    //当前的温度
    ui->labelcurrenttemp->setText(days[0]._Temp + "℃");
    qDebug() << days[0]._Temp;
    //温度的区间
    ui->labeltemp->setText("温度区间:" + days[0]._TempLow + "~" + days[0]._TempHigh);
    //天气情况
    ui->labelweathtype->setText(days[0]._WeathType);
    //天气情况图片
    ui->labelpic->setPixmap(mTypeMap[days[0]._WeathType]);
    //感冒系数
    ui->labelganmao->setText("紫外线指数:" + days[0]._Tips);
    //风的方向
    ui->labelwindtext->setText(days[0]._FX);
    //风速
    ui->labelwinddata->setText(days[0]._FL);
    //pm2.5
    ui->labelPM25data->setText(days[0]._Pm25);
    //湿度
    ui->labelshidudata->setText(days[0]._Hu);
    //空气质量
    ui->labelairdata->setText(days[0]._Airq);

    for(int i = 0; i < 6; i++){
        _WeekList [i]->setText(days[i]._Week);//星期的显示
        _WeekList [0]->setText("今天");
        _WeekList [1]->setText("明天");
        _WeekList [2]->setText("后天");//week的显示
        QStringList dateList = days[i]._Date.split("-");
        _DateList [i]->setText(dateList.at(1) + "-" + dateList.at(2));//日期的显示
        int inxdex = days[i]._WeathType.indexOf("转");//查找 "转" 的位置
        if(inxdex != -1){
            pixMap = mTypeMap[days[i]._WeathType.left(inxdex)];//截取左边的天气
        }else{
            pixMap = mTypeMap[days[i]._WeathType];
        }
        pixMap = pixMap.scaled(_IconList[i]->size(), Qt::KeepAspectRatio, Qt::FastTransformation);//图片的缩放
        _IconList [i]->setPixmap(pixMap);//天气图片的显示
        _WeathList[i]->setText(days[i]._WeathType);//天气的显示
        QString airq = days[i]._Airq;
        _AirqList [i]->setText(airq);//空气质量的显示
        if(airq == "优"){
            _AirqList[i]->setStyleSheet("background-color: rgb(188, 255, 1);border-radius: 7px;");//改变背景色
        }
        if(airq == "良"){
            _AirqList[i]->setStyleSheet("background-color: rgb(255, 228, 19);border-radius: 7px;");//改变背景色
        }
        if(airq == "轻度"){
            _AirqList[i]->setStyleSheet("background-color: rgb(255, 55, 39);border-radius: 7px;");//改变背景色
        }
        if(airq == "中度"){
            _AirqList[i]->setStyleSheet("background-color: rgb(189, 41, 29);border-radius: 7px;");//改变背景色
        }
        if(airq == "重度"){
            _AirqList[i]->setStyleSheet("background-color: rgb(110, 24, 17);border-radius: 7px;");//改变背景色
        }

        _FXList[i]->setText(days[i]._FX);
        inxdex = days[i]._FL.indexOf("转");//查找 "转" 的位置
        QString fl;
        if(inxdex != -1){
            fl = days[i]._FL.left(inxdex);//截取左边的风力
        }else{
            fl = days[i]._FL;
        }
        _FLList[i]->setText(fl);
    }

    update();
}

void Widget::drawTempLineHigh()
{
    QPainter painter(ui->widget0404);
    painter.setBrush(Qt::red);
    painter.setPen(QColor(170, 85, 0));
    int sum = 0;
    int ava;
    int offSet = 0;
    int middle = ui->widget0404->height()/2;
    for(int i = 0; i < 6; i++){
        sum += days[i]._TempHigh.toInt();//6天温度的总和
    }
    ava = sum / 6;//温度的平均值

    QPoint point[6];
    for(int i = 0; i < 6; i++){
        point[i].setX(_AirqList[i]->x() + _AirqList[i]->width()/2);//计算点的x坐标
        offSet = (days[i]._TempHigh.toInt() - ava)*3;
        point[i].setY(middle - offSet);//计算点的y坐标

        painter.drawEllipse(point[i],2,2);//画出6个点
        painter.drawText(point[i], days[i]._TempHigh + "°");//画出当天的最高温度
    }
    for(int i = 0; i < 5; i++){
        painter.drawLine(point[i],point[i+1]);//画出曲线图
    }
}

void Widget::drawTempLineLow()
{
    QPainter painter(ui->widget0405);
    painter.setBrush(Qt::blue);
    painter.setPen(QColor(6, 224, 243));
    int sum = 0;
    int ava;
    int offSet = 0;
    int middle = ui->widget0404->height()/2;
    for(int i = 0; i < 6; i++){
        sum += days[i]._TempLow.toInt();//6温度的总和
        qDebug() << days[i]._TempLow.toInt();
    }
    ava = sum / 6;//温度的平均值

    QPoint point[6];
    for(int i = 0; i < 6; i++){
        point[i].setX(_AirqList[i]->x() + _AirqList[i]->width()/2);
        offSet = (days[i]._TempLow.toInt() - ava)*3;
        point[i].setY(middle - offSet);

        painter.drawEllipse(point[i],2,2);
        painter.drawText(point[i], days[i]._TempLow + "°");
    }
    for(int i = 0; i < 5; i++){
        painter.drawLine(point[i],point[i+1]);
    }
}

//读取天气的数据
void Widget::readHttpRply(QNetworkReply *reply)
{
    int reCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();//状态码的捕获
    if(reply->error() == QNetworkReply::NoError && reCode == 200){
        qDebug() << reCode;
        QByteArray readBuf = reply->readAll();//读取天气的数据
        parseCurrentWeatherJsonDatanew(readBuf);//解析天气的Json数据
        //qDebug() << QString::fromUtf8(readBuf);
    }else{
        qDebug() << reCode;
        QMessageBox mes;
        mes.setWindowTitle("错误");
        mes.setText("网络请求失败" + QString::number(reCode) + "    ");
        mes.setStyleSheet("QPushButton {color:black}");//设置按键的样式表
        mes.exec();
    }
}

//搜索城市
void Widget::on_pushButton_clicked()
{
    QString currentCityName = ui->lineEditsearch->text();
    QString cityCode = citynames.getCityCodeid(currentCityName);//获取到城市的ID
    qDebug() << cityCode;
    if(cityCode != NULL){
        QString url = "http://v1.yiketianqi.com/api?unescape=1&version=v9&appid=17212311&appsecret=wgJCYY4x&cityid=" + cityCode;
        qDebug() << url;
        manager->get(QNetworkRequest(QUrl(url)));//发起get请求
    }else{
        QMessageBox mes;
        mes.setWindowTitle("错误");
        mes.setText("请输入正确的城市名称");
        mes.setStyleSheet("QPushButton {color:black}");//设置按键的样式表
        mes.exec();
    }
}

void Widget::on_lineEditsearch_returnPressed()
{
    on_pushButton_clicked();
}

5.2.1day.h

#ifndef DAY_H
#define DAY_H

#include <QString>

class day
{
public:
    day();

    QString _Date;
    QString _Week;
    QString _WeathType;
    QString _Temp;
    QString _TempLow;
    QString _TempHigh;
    QString _FX;
    QString _FL;
    QString _Airq;
    QString _Tips;
    QString _Hu;
    QString _City;
    QString _Pm25;
};

#endif // DAY_H

 5.2.2day.cpp

#include "day.h"

day::day()
{

}

5.3.1cityname.h

#ifndef CITYNAME_H
#define CITYNAME_H

#include <QMap>
#include <QString>

class CityName
{
public:
    CityName();

    QMap<QString, QString> cityMap;

    QString getCityCodeid(QString cityName);
    void initCityName();
};

#endif // CITYNAME_H

5.3.2cityname.cpp

#include "cityname.h"

#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>

CityName::CityName()
{

}

//获取对应城市的ID
QString CityName::getCityCodeid(QString cityName)
{
    //防止多次调用,减小开销
    if(cityMap.isEmpty()){
        initCityName();//获取城市名字初始化
    }

    QMap<QString, QString>::iterator it = cityMap.find(cityName);//从Qt的键值对中通过城市的名字寻找
    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 "";//在QMap中发现 名字后边都不带 市 县 区三个关键字的返回空
        }
    }
    return it.value();
}

//获取城市名字初始化
void CityName::initCityName()
{
    QFile file(":/citycode.json");
    file.open(QIODevice::ReadOnly);
    QByteArray rawData = file.readAll();//读取JSON文件保存到QByteArray中
    file.close();

    QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData);//把QByteArray转成JSONDoc
    if(jsonDoc.isArray()){
        QJsonArray citys = jsonDoc.array();//把JsonDoc转成QJsonArray
        for(QJsonValue val : citys){
            if(val.isObject()){
                QString cityName = val["city_name"].toString();//解析普通键值对,通过 变量+[" "] 来获取值
                QString cityCode = val["city_code"].toString();
                cityMap.insert(cityName, cityCode);//将获取到的城市名称和城市ID添加到Qt的键值对中
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值