QT实现天气预报软件

本文实现从中国天气网使用HTTP请求获得并解析天气信息

实现原理

     在这里,qt只是一个实现soft的工具,而且要学的就是这个工具,所以先说怎么实现天气预报软件,然后再一步一步说qt。

     需要弄明白的就一件事,怎么获取天气数据,网上一大堆,我这里精简下;

就是给天气服务器发送GET请求,这个属于HTTP协议的范畴,具体可以去研究下,这个能学到不少东西哟。

     这里有一个天气服务器:

     http://www.weather.com.cn/data/sk/101010100.html

     http://www.weather.com.cn/data/cityinfo/101010100.html

     http://m.weather.com.cn/data/101010100.html

     这样,我们只要建立一个QTcpSocket套接字,host为www.weather.com.cn,

最下面找出同位置的一样,端口号为80(HTTP服务的标准端口),然后建立好链接之后发送host后面的内容:

GET /data/cityinfo/101010100.html HTTP/1.1rnrn

     然后接受从服务器传过来的数据,解析,显示,over。那问题来了,怎么知道是哪个城市,上面那条命令里面的一串数字就是城市ID。

     http://blog.csdn.net/hello_haozi/article/details/7564223这个博客里面说的很详细,而且在上传的源代码包里面有处理过的城市列表,只是针对我这个程序的文件。

    根据IP获取ID:这个博客里面提到一个根据IP获取城市ID的,经过试验,只能获取到本地IP,那个城市ID不管在哪里都是显示的北京的ID。

 

调试方法

       调试我就用了两种方法:一个是qDebug() ;另外一个就是在界面设置一个QPlainTextEdit控件,这样能显示完全这些信息;

设计步骤:

一进行UI的设计

简单的设计如下

QT实现天气预报软件

部分控件介绍如下(转) 

      1、纲

       根据实现原理,首先肯定要有窗口小部件(QtWidgets class),显示文字(QLabel class),选择哪个地方的天气查看(QComboBox class),查看数据用于调试(QPlainTextEdit class),数据处理(QString class,QByteArray class,QFile class),还要中文化吧(QTextCodec class),最重要的要连接到天气服务器(QTcpSocket class,QAbastractSocket class等)。

 

       2、QWidget

       整个窗口就是一个widget小部件,有几种办法可以对界面进行设计(布局);一个是Qt Designer,qt creator也可以设计,这个文件后缀名为.ui;另外一个是直接写代码布局,通常就是layout;

       在这个widget中,我们通常需要和用户交互,这里就是响应事件;比如选择了某个省之后,我们点击一个按钮就获取服务器的天气预报数据,这是响应用户的鼠标事件;比如我们选定省的下拉列表(procomboBox)后,在市的下拉列表(citycomboBox)里面就显示该省有哪些市,同样,还有县级(coucomboBox),这里又要用到信号和槽了,这个是qt的核心功能;

        3、QLabel

       QLabel的默认大小为QSize(54,12),表示长度为54个像素,高度为12个像素,但是当天气为“中到大雨转阵雨”这么长的时候就显示不完全,这时候有两种办法来解决QLabel的显示问题:一个是QLabel::resize(QSize(200,12));另一个是QWidget::setGeometry(int x,int y,200,12),x和y是这个QLabel的坐标,后面是大小;

       QLabel显示图片,这个也有一个大小问题,通过qDebug()也能获取到图片大小,或者事先你就知道图片大小,然后进行resize

 

       4、QComboBox

       这个实现的是下拉框列表类,基本上看了他的成员函数,用到的就是他的一个信号currentIndexChanged,然后进行相关的处理;

 

       5、QPlainTextEdit

       这个只是用来调试,一个是setPlainText,一个是appendPlainText两个属性;

 

       6、数据处理

       这里就是个比较关键的地方。

      把城市名  和城市ID放到一个文件中,然后直接在每次启动软件的时候存入一个QMap<QString,QString>这样一个容器中,方便选择的时候直接查询到城市ID。

       数据处理我思考了两个问题,一个是怎么能让三个QComboBox空间联系起来,意思就是说选择省,那么下一个控件就只显示该省的所有市,同样下一个显示选中市的所有县;这样,第二个问题就是,关联起来用哪个数据结构存储数据,这个显然就用QMap最合适了,主要是利用他的键值对特性,但是究竟怎样关联,比如是QMap<QString,int>,还是QMap<QString,QString>,毕竟城市对应的是ID才能获取到天气数据呀;后来恍然大悟,反正我是要发送QString数据给服务器的,所以直接就用第二种了;所以最后的数据结构就用QMap<QString,QMap<Qstring,QStringList>>,这样就解决了所有的问题了。

       那当我们选中好一个城市之后,怎么找到ID,很简单,就直接从存储ID和城市对应的那个QMap容器里面找就是了。

     7、QAbstractSocket,QTcpSocket

       我们怎么连接上服务器呢悉TCP/IP的可能很容易就想到用套接字了,QT里面提供的也是极简单的套接字,QTcpSocket;由于我们这个连接的是HTTP服务器,所以理所当然,我第一个想到的是利用QT的HTTP接口,发现不好用,然后就直接用了套接字,我们连接的域名是www.weather.com.cn,所以直接用QAbstractSocket::connectToHost(www.weather.com.cn,80),HTTP众所周知的端口是80,去看看qt的manual就知道,当连接上的时候发送connected信号,在套接字上有数据的时候发送readready信号,这样我们就能够对数据进行处理了,这个不难;

下面进行代码的讲解:

QAbstractSocket,QTcpSocket提供了方便的信号机制,链接成功后返回connected信号,当有数据返回时有SIGNAL(readyRead()),可以说比较方便,先看下我的信号和槽的链接,然后后面会实现相应的槽的说明(详细的请查找代码csdn:QT4天气预报程序):

    connect(tcpsocket, SIGNAL(readyRead()), this, SLOT(readFortune()));
    connect(tcpsocket, SIGNAL(connected()), this, SLOT(sendRequest()));
    connect(tcpsocket, SIGNAL(disconnected()), this, SLOT(disconnectHost()));

    connect(ipAddrSocket, SIGNAL(readyRead()), this, SLOT(readIpAddr()));
    connect(ipAddrSocket, SIGNAL(connected()), this, SLOT(sendGetIpReq()));

ipAddrSocket用于获取本地的IP地址,是通过请求http://61.4.185.48:81/g/实现的;tcpsocket用于请求天气信息通过请求www.weather.com.cn实现。

ipAddrSocket->connectToHost(“61.4.185.48”,80);//根据IP获得城市代码:http://61.4.185.48:81/g/

readIpAddr()槽处理返回的IP信息

void Widget::readIpAddr()
{
    qDebug() << “ipAddr” ;
    QString s = ipAddrSocket->read(1024);

    ui->plainTextEdit->appendPlainText(s);

    /**/
    QStringList slist = s.split(“_”);
    qDebug() << slist[1];
    qDebug() <<slist[2];
    ui->ipLabel->resize(200,12);
    ui->ipLabel->setText(slist[1]);

    //测试正则式控制字符串
    QStringList elist = slist[2].split(QRegExp(“\W+”), QString::SkipEmptyParts);
    qDebug() << elist;

    //得到your city’s ID.
    for(int i=0; i< 4; i++)
    {
        if((!elist[i].isNull())&&(elist[i] == “id”))
            localCityID = elist[++i];
    }

    //set you count to combox
 //   ui->procomboBox->setCurrentIndex();
 //   ui->citycomboBox->setCurrentIndex();
    //链接天气网,提供初始天气信息
    tcpsocket->connectToHost(“www.weather.com.cn”,80);
}

PS:HTTP请求的格式请另找参考,这里时HTTP 1.0的,网上找的程序因为有的HTTP请求版本写成了1.1而无法运行。

另外程序中存在一些问题:

1.自动获取位置不成功(获取到的都是北京的)

2.程序刚启动时,选择框里面的城市是上海,不能根据自动获取的位置改变。

3.有些县市在列表中找不到

(allcity QMap中(key,value)也不合理,如果存在相同名字的地方后面的会被覆盖掉)

来源:guo8113

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2014年1月10日
下一篇 2014年1月10日

相关推荐