imxiangzi的专栏

不炼金丹不坐禅, 不为商贾不耕田. 闲来写就青山卖, 不使人间造业钱.

Qt QGraphics 地图浏览 程序

好吧……又是你妹夫的技术博……

首先给出这份练习代码的微云连接:MapWithGraphics 。放心~~博主是好人,不会有毒的~~。其次啊…我总是给练习代码,所以乱七八糟的就别看太多了,只关注重点部分吧!主目录下那三个pic* 文件夹就是地图了,放到F盘下吧,不然程序启动就会崩溃哦…或者自己改代码里面那些读图片的地方也可以。
读者可以随意对这份代码进行修改和使用。
这份练习代码中使用了Qt 的Graphics View Framework 来实现地图浏览。首先强调它的实际应用场景,如有不符,请移步别处吧。
1、它不具备下载地图的功能。所有的地图都是事先准备好保存于本地的。
2、地图分割需要满足几个条件:a.每张地图等大(合理吧) b.一级地图为2x2方阵,二级地图为4x4 ,三级为8x8,就是每次都对半分。c.这个程序最多支持3级放大,如果有更多的地图或者更大的需求,就自己改代码吧。
       下面给出效果图:
一级:
 Qt QGraphics 地图浏览 程序 - soooYo - ☆χιΑο.处
         二级:
Qt QGraphics 地图浏览 程序 - soooYo - ☆χιΑο.处
         三级:
Qt QGraphics 地图浏览 程序 - soooYo - ☆χιΑο.处
是不是这个效果啊?
  + 是放大,  - 是缩小, 2,4,6,8是移动键。       

 下面是项目文件:
Qt QGraphics 地图浏览 程序 - soooYo - ☆χιΑο.处



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后,请调用一次
Qt QGraphics 地图浏览 程序 - soooYo - ☆χιΑο.处
这样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,虽然可能没有什么感觉,但是程序员心里都会痒痒的。
现在就来讲讲这个避免多余计算的算法。
程序会在最开始的时候收集图片的大小,窗口大小等信息。以计算出横向和纵向能最多容纳多少张图片。

Qt QGraphics 地图浏览 程序 - soooYo - ☆χιΑο.处
对于横向来说,如果屏幕宽度除以图片宽度等于X,那么当余数大于等2时,就能容下2+X张图片,如果余数恰好等于1,则容下1+X张图片。对于纵向来说也是一样的。应该不难理解。这样就得到了一个最大的横向和纵向的最大容纳图片数。

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

Qt QGraphics 地图浏览 程序 - soooYo - ☆χιΑο.处
 
知道了centerItem在哪里,又知道最大的容纳数,剩下的就好办了。只检查从centerItem开始,横向到centerItem加上横向最大容纳数个Item,纵向也是。如下图(比较烂):
    Qt QGraphics 地图浏览 程序 - soooYo - ☆χιΑο.处
 蓝色框就是可见的场景,因为左上角落在最上面的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/

阅读更多
个人分类: QT/视图图形
想对作者说点什么? 我来说一句

Qt 地图 Map

2012年10月29日 464KB 下载

Qt写的谷歌地图示例

2013年12月25日 1.43MB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭