您的位置:首页 > 编程语言 > Qt开发

Qt QGraphics 地图浏览 程序

2015-10-30 13:18 295 查看
好吧……又是你妹夫的技术博……

首先给出这份练习代码的微云连接:MapWithGraphics 。放心~~博主是好人,不会有毒的~~。其次啊…我总是给练习代码,所以乱七八糟的就别看太多了,只关注重点部分吧!主目录下那三个pic*
文件夹就是地图了,放到F盘下吧,不然程序启动就会崩溃哦…或者自己改代码里面那些读图片的地方也可以。

读者可以随意对这份代码进行修改和使用。

这份练习代码中使用了Qt 的Graphics View Framework 来实现地图浏览。首先强调它的实际应用场景,如有不符,请移步别处吧。
1、它不具备下载地图的功能。所有的地图都是事先准备好保存于本地的。
2、地图分割需要满足几个条件:a.每张地图等大(合理吧) b.一级地图为2x2方阵,二级地图为4x4 ,三级为8x8,就是每次都对半分。c.这个程序最多支持3级放大,如果有更多的地图或者更大的需求,就自己改代码吧。
下面给出效果图:
一级:



二级:



三级:



是不是这个效果啊?
+ 是放大, - 是缩小, 2,4,6,8是移动键。


下面是项目文件:



CustomeItem 忘了是出于什么原因重写的了。但是如果你要重写QGraphicsItem,一定要先好好看看Qt的手册,有一些函数是必须重写的,有特定要求。CustomePixmap是为了检查GraphicsScene在清除场景中的Item时,是否会调用Item的析构函数,手册说是会的,而笔者也验证过了------真的会哦亲~~~~!读者只需要留意GraphicsMap即可。其他都是垃圾代码。

一些注意的地方:

1、QPixmap比较不省内存。正如手册里面说的,QPixmap的出现就是为了加速图片的显示,为了保证显示的流畅,QPixmap实际用到一些缓冲,这就让它比较大了。你可以用QImage来代替QPixmap,问题是当你连续按住移动键的时候,程序会停住。因为QImage的显示速度远远不及QPixmap,它要慢慢加载。另外,delete了一个QPixmap,是看不到堆空间马上就释放的,系统会在较后的时间才回收这些资源。而delete
QImage就不同了,堆空间会马上释放掉。关于这部分的原因,建议读者自行百度一下“QPixmap QImage “,网上有很多理论很深的介绍,不妨充实自己。



2、QGraphicsScene只会扩大不会缩小?? 不,不是的。手册的原话是会随着添加到场景中的Item的BoundingRect而变化。当你向一个Scene中塞满了Item后,Scene就会撑大,随后你remove了里面所有的Item,会发觉scene->sceneRect保持不变。不要紧,当你再向场景中添加完Item后,请调用一次



这样scene就会重新计算一次自己的大小了。这一步骤在这个程序比较重要,因为程序决定要显示哪些图片是要通过大小和位置来确定的。

3、分清楚View的sceneRect() 和Scene的sceneRect()的不同。View 的sceneRect()是当前View可见的那部分场景。而Scene的sceneRect()是场景本身的实际大小。就不多说了。

4、delete了scene就别去delete它的Item了。会导致重复delete的,会崩溃。

另外,为了节省内存,程序不会将所有图片都load内存中,它只事先准备好一些空的QGprahicsItem,当这个Item暴露在可见的场景之下时,才会去load一张对应的Pixmap。当然,当Item完全退出了可见场景后,就会将自己的Pixmap置空。这个操作就会导致那个Pixmap的内存被释放掉。

当然,为了提高效率,程序是不会每次都遍历所有的Item来看看谁在可见场景,谁不在可见场景的。当Item去到64个的时候,每移动一次就要检查64个Item,虽然可能没有什么感觉,但是程序员心里都会痒痒的。

现在就来讲讲这个避免多余计算的算法。

程序会在最开始的时候收集图片的大小,窗口大小等信息。以计算出横向和纵向能最多容纳多少张图片。



对于横向来说,如果屏幕宽度除以图片宽度等于X,那么当余数大于等2时,就能容下2+X张图片,如果余数恰好等于1,则容下1+X张图片。对于纵向来说也是一样的。应该不难理解。这样就得到了一个最大的横向和纵向的最大容纳图片数。

还需要确定一个”中心”Item。这个中心打双引号的原因是它根本不是在中间的。只是当时命名的时候一时用了centerItem,就没改了。其实这个centerItem就是View的sceneRect()得到的左上角坐标所做的那个Item。是的,这就是centerItem。每次移动的时候,都会计算一下view的sceneRect左上角落在哪个Item上:





知道了centerItem在哪里,又知道最大的容纳数,剩下的就好办了。只检查从centerItem开始,横向到centerItem加上横向最大容纳数个Item,纵向也是。如下图(比较烂):





蓝色框就是可见的场景,因为左上角落在最上面的Item上,所以它是centerItem,检查它往右的横向最大容纳数个Item,检查它向下的纵向最大容纳数个Item。其他Item不检查。

至于判断是否要load图片,就看看item的Rect跟可见的场景是否有交集,QRect有一个关于求交集的函数,只要判断交集不为空,则该Item暴露在可见场景内,就要load图片。

这个避免多余计算的算法其实是有漏洞的,希望读者能够自己着力修改一番。


通过观察任务管理器,可以发现内存占用是比较小的。当使用到3级地图时,内存占用13,000k左右。此时进行缩小,发现内存占用不变。其实不是不变,而是变得比较慢。这就是注意问题中提到的第一点了。
剩下的部分就交给读者自己去理解了。这个小程序很简单,喜欢就拿去用吧~~

Enjoy your Qt.

FROM: http://blog.163.com/soyo_gogogo/blog/static/171414077201352011041694/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: