Qt实现天气信息显示和温度曲线绘制

最近在学习如何获取天气信息并展示,通过总结别人博客加自己的理解, 使用Qt写了一版天气预报。

 

城市搜索功能

该功能模块可以实现从Lineedit获取用户输入的城市,处理后获取对应的天气信息。

#include <QNetworkAccessManager>
#include <QNetworkReply>

protected:
Q_INVOKABLE void getWeatherInfo(QString cityName);  // 通过城市编码获取天气信息
private:
QNetworkAccessManager *mNetAccessManager;// Http请求

//获取天气信息
void Weather::getWeatherInfo(QString cityName)
{
    QString cityCode= getCityCode(cityName);
    if(cityCode.isEmpty())
    {
      return;
    }
    QUrl url("http://t.weather.itboy.net/api/weather/city/"+cityCode);
    mNetAccessManager->get(QNetworkRequest(url));
}

请求的url为 http://t.weather.itboy.net/api/weather/city/cityCode

cityCode为城市编码,每一个城市对应一个编码,例如北京的编码为101010100, 替换上述链接的cityCode即可查询北京的天气。对于不同城市的编码可以从网上下载后(JSON格式)放入Qt的资源文件,当我们输入一个城市查询天气时,可以读资源文件找到对应城市的编码,将编码替换cityCode后获取天气信息

天气信息显示

因为获取信息需要联网,需要在pro文件增加 QT += network 并引入头文件QNetworkAccessManager和QNetworkReply

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonParseError>

//网络对象
mNetAccessManager=new QNetworkAccessManager(this); 
connect(mNetAccessManager,SIGNAL(finished(QNetworkReply*)),this,SLOT(onReplied(QNetworkReply *)));

// 处理HTTP服务返回数据
void Weather::onReplied(QNetworkReply *reply)
{
    int statusCode=reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    if(statusCode!=200 || reply->error()!=QNetworkReply::NoError)
    {
        QMessageBox::warning(this,"天气","请求数据失败",QMessageBox::Ok);
    }
    else
    {
        QByteArray byteArray=reply->readAll();
        parseJson(byteArray);// 分析Json数据
    }
    reply->deleteLater();//延时释放,防止堆区的接收数据泄漏
}

请求到的数据为JSON格式,需要用到QJson相关的头文件进行JSON解析,此处不详细介绍,主要思路是先构建出QJsonObject,依次解析日期和城市、未来5天数据、今日天气数据(根据回复的JSON结构体进行处理),将需要的信息显示在界面上,包括温湿度、风力等信息。

这里我们最好建立一个包含这些信息的类来存储上述信息。

class Info{
public:
    QString date;   // 日期
    QString city;   //城市
    QString ganmao; //感冒
    int wendu;  // 温度
    QString shidu;  // 湿度
    int pm25;   //   pm2.5
    QString quality;    //质量
    QString type;   // 天气类型
    QString fx; //风向
    QString fl; //风力
    int high;   //高温
    int low;    //低温
};

温度曲线绘制

这里我们重写父类的eventFilter方法。

protected:
    bool eventFilter(QObject* watched,QEvent *e);
    void paintHighCurve();//绘制高温曲线
    void paintLowCurve();//绘制低温曲线

// 重写父类的eventFilter方法
bool Weather::eventFilter(QObject *watched, QEvent *e)
{
    if(watched == ui->HighCurve&& e->type() == QEvent::Paint){
        paintHighCurve();
    }
    if(watched == ui->LowCurve&& e->type() == QEvent::Paint){
        paintLowCurve();
    }
    return QWidget::eventFilter(watched,e);
}

绘制主要使用QPainter类, 采用drawEllipse函数进行点的绘制, 采用drawLine函数进行线的绘制。

//绘制高温曲线
void Weather::paintHighCurve()
{
    QPainter painter(ui->HighCurve);// 画家类
    painter.setRenderHint(QPainter::Antialiasing,true);
    // 1. 获取x轴坐标
    int pointX[6]={0};
    for(int i=0;i<6;i++){
        pointX[i]=mWeekList[i]->pos().x()+(mWeekList[i]->width()/3);
    }
    // 2. 获取y轴坐标
    int tempSum=0;//总和
    int tempAverage=0;//平均
    for(int i=0;i<6;i++){
        tempSum+=mDay[i].high;
    }
    tempAverage=tempSum/6; // 最高温的平均值
    // 计算y轴坐标
    int pointY[6]={0};
    int yCenter = ui->lblHighCurve_4->height()/2;
    for(int i=0;i<6;i++){
        pointY[i]=yCenter - ((mDay[i].high-tempAverage)*INCREMENT);
    }
    // 3. 开始绘制
    QPen pen=painter.pen();
    pen.setWidth(1);  
    pen.setColor(QColor(255,170,0)); //设置画笔的颜色
    painter.setPen(pen);//给画家设置画笔
    painter.setBrush(QColor(255,170,0));//设置画刷的颜色-内部填充的颜色
    // 3.2 画点、画文字
    for(int i=0;i<6;i++){
        // 显示点
        painter.drawEllipse(QPoint(pointX[i],pointY[i]),POINT_RADIUS,POINT_RADIUS);
        // 显示温度
        painter.drawText(pointX[i]-TEXT_OFFSET_X,pointY[i]-TEXT_OFFSET_X,
                         QString::number(mDay[i].high));
    }
    // 3.3绘制曲线
    for(int i=0;i<6-1;i++){
        if(i == 0){
            pen.setStyle(Qt::DotLine);//虚线
            painter.setPen(pen);
        }else{
            pen.setStyle(Qt::SolidLine);//虚线
            painter.setPen(pen);
        }
        painter.drawLine(pointX[i],pointY[i],pointX[i+1],pointY[i+1]);
    }
}

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
下面是一个简单的Qt绘制温度曲线的示例: ```C++ class TemperatureWidget : public QWidget { Q_OBJECT public: TemperatureWidget(QWidget *parent = nullptr) : QWidget(parent) { // 设置背景颜色 QPalette pal(palette()); pal.setColor(QPalette::Background, Qt::white); setAutoFillBackground(true); setPalette(pal); // 设置绘图区域 rect = QRect(50, 10, 300, 200); // 设置温度范围 minTemperature = -20; maxTemperature = 50; // 创建温度数据采集线程 thread = new TemperatureThread(this); // 连接数据信号和槽函数 connect(thread, &TemperatureThread::newTemperature, this, &TemperatureWidget::updateTemperature); // 启动温度数据采集线程 thread->start(); } protected: void paintEvent(QPaintEvent *event) override { Q_UNUSED(event); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); // 抗锯齿 // 绘制坐标轴 painter.drawLine(rect.topLeft(), rect.bottomLeft()); painter.drawLine(rect.bottomLeft(), rect.bottomRight()); // 绘制温度曲线 painter.setPen(QPen(Qt::red, 2)); painter.drawPolyline(points.data(), points.size()); } private: QRect rect; // 绘图区域 double minTemperature; // 温度范围 double maxTemperature; QList<QPointF> points; // 温度数据点 TemperatureThread *thread; // 温度数据采集线程 void updateTemperature(double temperature) { // 新增温度数据点 QPointF point(points.size(), rect.bottom() - (temperature - minTemperature) * rect.height() / (maxTemperature - minTemperature)); points.append(point); // 删除超出绘图区域的温度数据点 while (points.size() > rect.width()) points.removeFirst(); // 更新UI界面 update(rect); } }; // 温度数据采集线程类 class TemperatureThread : public QThread { Q_OBJECT public: TemperatureThread(QObject *parent = nullptr) : QThread(parent) {} signals: // 定义一个新温度信号 void newTemperature(double temperature); protected: void run() override { while (!isInterruptionRequested()) { // 实时采集温度数据 double temperature = getTemperature(); // 发送新温度信号 emit newTemperature(temperature); // 休眠一段时间 msleep(1000); } } private: double getTemperature() { // 模拟温度数据采集 static double temperature = 20.0; temperature += (qrand() % 21 - 10) / 10.0; if (temperature < -20) temperature = -20; if (temperature > 50) temperature = 50; return temperature; } }; ``` 在上面的示例中,TemperatureWidget是一个温度曲线显示界面类,负责在UI界面上绘制温度曲线,并启动TemperatureThread线程进行温度数据采集。TemperatureThread是一个温度数据采集线程类,负责实时采集温度数据,并将数据通过newTemperature信号发送给UI线程。通过connect函数将newTemperature信号连接到updateTemperature槽函数,从而实现温度曲线的实时显示。 在paintEvent函数中,首先绘制坐标轴,然后根据温度数据点绘制温度曲线。updateTemperature函数用于将新采集到的温度数据转换成图像坐标,并新增到温度数据点序列中,然后删除超出绘图区域的温度数据点,最后调用update函数刷新UI界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值