实现原理
在这里,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的设计
简单的设计如下
部分控件介绍如下(转)
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)也不合理,如果存在相同名字的地方后面的会被覆盖掉)
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!