Qt项目(6)Qt实现天气预报

在这里插入图片描述

1. 场景简介

WeatherWebService网站提供了获取天气数据的访问接口,不过对于免费的用户来讲,一天只能访问50次,超出之后需要付费。本身就提供了查询城市ID,支持城市列表,通过城市ID可以找到对应城市的照片等多个接口。当然,通过这个接口,可获取天气数据到本地。然后对天气数据进行分析,最终显示到界面上。最终的话可以把界面做的漂亮一点,把功能完善一下,甚至可以做一些可视化的数据分析,提供出行建议等。由于上网不是很方便,这里只做了基本的功能,界面也做的略显ugly。除了访问接口之外,网站还提供了接口说明,天气图标,城市图标等资源。
对于用户来讲,呈现的功能有,输入全国任一城市,单击查询按钮,界面将显示实时的温度、日期、图标;当天的天气情况、温度范围、风力大小、以及一些温馨提示; 关于城市的简介、城市的图片(我没做)。默认情况下显示的是西安的天气情况。

2. 步骤与思路

1.从网站接口获取天气数据,使用到的是Qt实现Http请求的知识,即本地计算机作为客户端向该服务器发送Http请求,服务器响应天气数据,因此客户端需要接收并保存。发送Http请求的方式有多种,可以使用Post带参数(指哪个城市)结合网站提供的getweather方法来访问,也可以使用get请求,直接将城市名作为Url的一部分,交给Qt来解析。我用的是第二种方法。
2.获取到的天气数据其实是xml文件,用到的是Qt中使用XML格式文档的知识,就是如何读取本地的xml文件,从中获得可用信息并存储到全局变量中。天气数据xml的构成很简单,一共两级目录,第一级是一些简介,无关痛痒;第二级是天气信息,节点名字统统叫做QString,文本值即有效信息。通过数数的方式判断数据内容。如下图所示。
在这里插入图片描述
3.根据全局变量中的数据刷新界面,多数界面部件是QLabel,该显示图的显示图,显示字的显示字即可。具体的步骤结合代码及其注释。

3. 代码

main文件

#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

.h文件

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QFile>
#include <QMessageBox>
#include <QDateTime>
#include <QDate>
#include <QDomDocument>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    Ui::Widget *ui;
    QNetworkAccessManager *manager;
    QNetworkReply *reply;
    QFile *myFile;//xml写

    QString str_utl;//网址字符串
    QString filename;//xml文件名
    QString def_city;//默认城市名
    QString iconPath;//天气图标ICON
    QString strProvince;//省份
    QString strCity;//城市名
    QString strTempr;//温度范围
    QString strWeather;//今日天气
    QString strIcon;//图标名字
    QString strWind;//风力
    QString strCurWeather;//实时天气
    QString strTips;//温馨提示
    QString strCityHistory;//城市历史
    void Init();//初始化函数
    void myHttpGetWeather(QString);//http请求下载xml天气文件
    void myiRefreshUi();//根据xml文件的解析结果刷新界面
    bool myDecodeXml();//解析xml文件
private slots:
    void doProcessReadyRead();
    void doProcessError(QNetworkReply::NetworkError);
    void doProcessFinished();
    void on_query_btn_clicked();
};
#endif // WIDGET_H

.cpp文件

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    Init();

}
Widget::~Widget()
{
    delete ui;
}
void Widget::Init()
{
    str_utl.clear();
    filename.clear();
    def_city.clear();
    strProvince.clear();
    strCity.clear();
    strWind.clear();
    strTempr.clear();
    strWeather.clear();
    strIcon.clear();
    strCurWeather.clear();
    strTips.clear();
    strCityHistory.clear();
    iconPath.clear();

    ui->lab_cityHistory->adjustSize();//控件大小与内容自适应
    ui->lab_cityHistory->setWordWrap(true);//自动换行
    ui->lab_cityHistory->setAlignment(Qt::AlignTop);
    iconPath = QString(":/myWeather/");
    str_utl.append("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=");
    filename = QString("woshi.xml");//获取到的天气数据
    def_city = "西安";
    myFile = new QFile(this);
    myFile->setFileName(this->filename);//获取或创建文件
    manager = new QNetworkAccessManager(this);
    if(filename.isEmpty()){
        return;
    }
    //获取默认城市 上海市的天气,并据此初始化各个界面部件
    myHttpGetWeather(def_city);
    //各界面部件初始化
//    myiRefreshUi();
}
void Widget::myHttpGetWeather(QString str_city)//str = 城市名
{
    QString current_addr;
    QUrl myUrl;
    QNetworkRequest myReq;//准备网络请求
    current_addr.clear();
    current_addr.append(str_utl).append(str_city);//当前查询城市网址
    myUrl.setUrl(current_addr);//设置网络请求的url
    myReq.setRawHeader(QByteArray("User-Agent"),QByteArray("MyOwnBrowser 1.0"));//设置http包的请求头
    myReq.setUrl(myUrl);
    bool ret = myFile->open(QIODevice::WriteOnly|QIODevice::Truncate);//以重写的方式打开,在写入新的数据时会将原有
    if(!ret){
        QMessageBox::warning(this,"warning","myHttpGetWeather失败!");
        return;
    }
    reply = manager->get(myReq);//发送http get请求
    connect(reply,SIGNAL(readyRead()),this,SLOT(doProcessReadyRead()));//数据来临的信号,IO操作大多数都是这个信号
    connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(doProcessError(QNetworkReply::NetworkError)));
    connect(reply,SIGNAL(finished()),this,SLOT(doProcessFinished()));//传输(一次应答)完成

}
//根据所得xml天气信息刷新界面
void Widget::myiRefreshUi()
{
    //获取当前时间
    QDateTime c_time = QDateTime::currentDateTime();
    QString str_week = c_time.toString("ddd");//获取星期
    QDate date = QDate::currentDate();
    QString labDataTime;
    labDataTime.append(QString::number(date.year()));
    labDataTime.append("年");
    labDataTime.append(QString::number(date.month()));
    labDataTime.append("月");
    labDataTime.append(QString::number(date.day()));
    labDataTime.append("日");
    labDataTime.append(" ");
    labDataTime.append(str_week);

    //获取xml天气信息
    if(!myDecodeXml()){
        return;
    }
    //刷新界面
    //0.刷新省份城市
    QString tempCity;
    tempCity = strProvince.append(" ");
    tempCity = tempCity.append(strCity);
    ui->url_edit->setText(tempCity);
    //1.刷新时间界面
    ui->lab_Datatime->setText(labDataTime);
    //2.刷新天气图标
    QString tempIconPath = iconPath;
    tempIconPath.append(strIcon);
    qDebug()<<tempIconPath;
    QPixmap pix(tempIconPath);
    pix = pix.scaled(QSize(100,100));
    ui->lab_wetherIcon->setPixmap(pix);
    //3.刷新实时温度值
    qDebug()<<"实时天气情况:"<<strCurWeather;

    strCurWeather.remove("今日天气实况:");
    QStringList list1 = strCurWeather.split(";");//此处是中文输入下的分号
    QString tempTempr=list1.at(0);
    QStringList list2 = tempTempr.split(":");//此处是中文输入下的冒号
    QString realTempr = list2.at(1);
    qDebug()<<list1.at(0)<<list2.at(1);
    ui->lab_realTemp->setText(realTempr);
    //4.刷新温度值

    ui->lab_tempRange->setText(strTempr);
    //5.刷新今日天气
    ui->lab_wethStatus->setText(strWeather);
    //6.刷新风力
    ui->lab_wind->setText(strWind);
    //7.刷新温馨提示
    ui->lab_tips->setText(strTips);
    //8.刷新城市历史
    ui->lab_cityHistory->setText(strCityHistory);
    //9.刷新城市照片
}
//解析xml文件,为全局变量赋值
bool Widget::myDecodeXml()
{
    if(myFile->isOpen()){
        myFile->close();
    }
    bool ret = myFile->open(QIODevice::ReadWrite);//以重写的方式打开,在写入新的数据时会将原有
    if(!ret){
        QMessageBox::warning(this,"warning","myDecodeXml打开失败!");
        return false;
    }
    QDomDocument doc("yxx");//定义doc对象,初始化名字
    QString error;
    int line, column;
    bool isLot = doc.setContent(myFile, &error, &line, &column);//将文件与QDomDocument类关联
    if(!isLot){
        //关联xml文件失败
        myFile->close();
        qDebug() << "Error:" << error << "in line " << line << "column" << column;
        QMessageBox::warning(this,"waring","myDecodeXml关联失败");
        return false;
    }
    myFile->close();
    QDomElement firstElem = doc.documentElement();//获取到了<ArrayOfString>一级目录
    QDomNodeList secondList = firstElem.childNodes();//获取全部二级目录<QString>
    for (int i = 0; i < secondList.count(); ++i) {
       QDomElement secondElem = secondList.at(i).toElement();//获取二级目录节点的属性值管理者domElement
       if(i==0){//获取省份
           strProvince = secondElem.text();
       }
       if(i==1){//获取城市名
           strCity = secondElem.text();
       }
       if(i==5){//获取温度
           strTempr = secondElem.text();
       }
       if(i==6){//获取天气情况
           QString tempStr;
           tempStr = secondElem.text();
           QStringList list = tempStr.split(" ");
           strWeather = list.at(1);
       }
       if(i==7){//获取风力
           strWind = secondElem.text();
       }
       if(i==8){//获取天气图标
           QString tempIcon = secondElem.text();
           QStringList list3 = tempIcon.split(".");
           QString tempIcon2 = list3.at(0);
           strIcon = tempIcon2.append(".png");
       }
       if(i==10){//获取实时天气情况
           strCurWeather = secondElem.text();
       }
       if(i==11){//获取温馨提示
           strTips = secondElem.text();
       }
       if(i==22){//获取城市介绍
           strCityHistory = secondElem.text();
       }
    }
    qDebug()<<"执行完毕xmldecode";
    return true;
}
//查询按钮槽函数
void Widget::on_query_btn_clicked()
{
    //获取地址
    QString city = ui->url_edit->text();//获取城市名字
    if(!city.isEmpty()){
        myHttpGetWeather(city);//获取当前城市的xml天气文件
    }
}
//数据来临槽函数
void Widget::doProcessReadyRead()
{
    //读取应答数据,并且写入文件中
    while(!reply->atEnd()){
        QByteArray ba = reply->readAll();
        myFile->write(ba);
    }
}
//过程出错槽函数
void Widget::doProcessError(QNetworkReply::NetworkError err)
{
     qDebug()<<"接收过程出错"<<reply->errorString();
     qDebug()<<err;
}
//请求过程结束信号
void Widget::doProcessFinished()
{
    qDebug()<<"接收数据完毕!";
    myFile->close();//强制刷新
    myiRefreshUi();
}

4. 效果与总结

效果:
在这里插入图片描述
总结:

  • 1.有一个城市风貌的图片我没做,可以结合WeatherWebService网站提供的资源完善一下。
  • 2.QLabel设置Text值的时候请注意,给的参数为QString,这个QString过长的话,部件不换行会拉的很长。让部件与文本自适应,自动换行,自动调整大小。如下:
	labelName->adjustSize();//控件大小与内容自适应
    labelName->setWordWrap(true);//自动换行
    labelName->setAlignment(Qt::AlignTop);
  • 3.Qt进行文件读写的IO操作,请注意,文件名有特殊字符,将会导致QIODevice::write (QFile, “woshi.xml”): device not open。另外还要注意,从服务器获取数据,相当于是服务器回来的数据要写入本地文件,对于天气数据的分析相当于是要读取同一个本地文件。那必须保证读操作与写操作之间不发生冲突,否则会出现各种错误。如何保证呢?可以等服务器数据传输finish,即发出fnish信号的时候设置状态标志,使用定时器或者线程监测这个标志,直到写完在进行读操作。也可以在finish信号的槽函数中调用分析数据的函数。 对于本文,用的是第二种方法。
  • 4.天气数据xml中的标点符号是中文输入的,在数据分析时要注意。使用到xml和network的类,记得现在.pro文件中

5.传送门

END

🎏文章原创,首发于CSDN论坛。
🎏欢迎点赞❤❤收藏⭐⭐打赏💴💴!
🎏欢迎评论区或私信指出错误❌,提出宝贵意见或疑问❓。


  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Qt是一个跨平台的应用程序开发框架,它提供了一组丰富的库和工具,可以帮助开发人员轻松地创建高质量、漂亮的UI界面设计。Qt可以满足各种开发需求,从桌面应用程序到移动应用程序,从嵌入式系统到图形用户界面等等。QtUI设计风格非常美观,而且非常易于使用。其界面布局精美,视觉效果出色,能够提供出色的用户体验。Qt提供了一些常用的UI控件,例如文本编辑器、按钮、列表、下拉列表和进度条等等。除此之外,Qt用于UI设计的编辑器Qt Designer也提供了一系列的模板和样式表的支持,可以帮助用户轻松创建自定义的UI界面。此外,Qt还通过其内置的QStyle类为开发人员提供了更多的灵活性,使得他们能够创建一个独特的、个性化的UI界面。总体来说,Qt是一个令人印象深刻的UI界面设计框架,它提供了一个优雅且美观的界面,可以帮助开发人员在各种平台和设备上开发出高质量的应用程序。 ### 回答2: Qt作为一个跨平台的开发框架,不仅提供了强大的工具和库,还拥有漂亮的UI界面设计。QtUI设计风格是流行的扁平化设计,使得界面看起来简洁、美观、易于操作。QtUI设计工具集成在Qt Creator中,使用方便,适合开发各种类型的应用程序。 Qt中的界面元素多样,包括按钮、文本框、标签、进度条、滑块等。QtUI设计支持自定义图标、颜色和字体,方便开发人员根据项目需求进行调整和个性化设计。Qt Creator提供了大量的预设模板,开发者可以快速创建应用程序的UI界面,同时也可以通过拖拽元素来构建UI界面,简单易用。 除了基本的UI元素外,Qt还提供了强大的图形引擎,支持高品质的图形渲染。Qt的图形引擎具有很好的表现力,能够处理各种类型的图像和动画,包括几何图形、贝塞尔曲线、PNG和SVG等矢量图形。将这些图形元素结合在一起,可以轻松地创建富有动感的UI界面,提升用户的体验。 总之,Qt具备漂亮的UI界面设计,其丰富的UI元素、可定制性和方便的开发工具使其成为了一个备受欢迎的跨平台开发框架。无论是开发桌面应用、移动应用还是嵌入式应用,QtUI设计都能满足开发者的需求,帮助他们轻松地实现美观的UI界面。 ### 回答3: Qt是一款功能强大、强调跨平台性的框架,它不仅提供了完整的基础库,同时还具备了漂亮的UI界面设计。QtUI界面设计分为前端设计和后端程序实现两个部分。 在前端设计方面,Qt提供了一系列的UI部件,这些部件在外形和样式上具有强大的灵活性。QtUI部件可以通过样式表来定义不同的外观和响应状态,这样可以方便地实现更加个性化的UI设计。此外,Qt还提供了QML语言,通过它可以创建精美的UI界面,同时还能实现C++代码的无缝结合。 在后端实现方面,Qt提供了一套完整的MVC框架,包括了数据层、业务逻辑层和UI层。这个框架能够有效地分离UI界面和后端业务逻辑,使得UI界面能够更加专注于具体的显示和交互。同时,Qt还提供了信号与槽机制,通过它可以实现对象间的通信,使得代码的编写更加简洁易读。 综上所述,Qt具备了漂亮的UI界面设计,并且提供了一套完整的UI框架,能够帮助开发者轻松实现个性化的UI设计和后端实现。这也是为什么Qt能够被广泛应用于GUI应用程序开发的原因之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

FPGA小油条

原创不易,请多支持

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

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

打赏作者

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

抵扣说明:

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

余额充值