引言

用Qt程序在手机上显示一幅图片对编程人员来说是再基础不过的一件事情了。那么先让大家看两段代码:

//dangerous should not be used, cannot display earth.png,  //but if we change earth.png to a smaller image e.g. apple.png, apple.png can be displayed QPixmap pixmap; pixmap.load( ":/pics/earth.png" ); label->setPixmap( pixmap );

//dangerous should not be used, cannot display earth.png,  //but if we change earth.png to a smaller image e.g. apple.png, apple.png can be displayed QPixmap pixmap; pixmap.load( ":/pics/earth.png" ); QPainter painter(this); painter.drawPixmap(0,0, pixmap);

大家认为这两段代码有什么问题吗? 
看起来好像没什么问题啊。是的,在Windows操作系统上是没有问题的。问题是我们做的是Qt for Symbian! 手机上的资源本来就是比较紧缺的,所以我们使用的时候就需要更加注意。 Qt 为我们提供了四个处理图像的类:QImageQPixmapQBitmap 和QPicture。其中前两个是最常使用的。

本文就通过一个例子,一步一步为大家讲解QImage与QPixmap的使用奥秘,在此过程中为大家揭示以上代码存在的缺陷。本文所用例子程序可通过本文末尾所附链接下载。

QPixmap依赖于硬件

首先需要知道的是QPixmap的具体实现是依赖于系统的。在Symbian系统上QPixmap是被存放在Server端的。

目前的Qt会把QPixmap都存储在graphics memory中,这明显是依赖硬件的。因此我们对QPixmap的使用需要格外注意。这也正是以上两段代码存在问题的根源。
那么Qt为什么要这么做呢?很简单,设计之初QPixmap就是用来加速显示的,例如我们在paint的时候用QPixmap就会比用其他类的效果好许多。

现在回到我们最初的问题,以上代码到底有什么问题呢?我们可以先用本文提供的例子程序做个试验。当使用上述代码显示较小图片的时候(比如例子程序中的background.png 和apple.png)是没有问题的,图片都能在手机上正确显示。
但是当我们把图片换成一副较大图片287KB,1058 x 1058的“earth.png”的时候就出现问题了,图片无法显示,程序的界面是一片空白。

据测算,“earth.png”被完全解码后存储在graphics memory中会占用大约4.3MB的空间。如果此时还有其他加载的窗口和QPixmap,很可能就没有空间了。

使用QImage加载后转换成QPixmap 显示

那么安全和正确的方法应该是什么呢?答案是我们需要用QImage做一下预处理:

//correct and recommended way QImage image; image.load( ":/pics/earth.png" );   QPainter painter(this); QPixmap pixmapToShow = QPixmap::fromImage( image.scaled(size(), Qt::KeepAspectRatio) ); painter.drawPixmap(0,0, pixmapToShow);

和QPixmap 不同,QImage是独立于硬件的,它可以同时被另一个线程访问。QImage是存储在客户端的,对QImage的使用是非常方便和安全的。 又由于 QImage 也是一种QPaintDevice,因此我们可以在另一个线程中对其进行绘制,而不需要在GUI 线程中处理,使用这一方式可以很大幅度提高UI响应速度。 
因此当图片较大时,我们可以先通过QImage将图片加载进来,然后把图片缩放成需要的尺寸,最后转换成QPixmap 进行显示。 下图是显示效果(图片是按照earth.png的原始尺寸比例缩放后显示的):

其中需要注意的是Qt::KeepAspectRatio的使用,默认参数是Qt::IgnoreAspectRatio,如果我们在程序中这么写:

QPixmap pixmapToShow = QPixmap::fromImage( image.scaled(size(), Qt::IgnoreAspectRatio) );

效果就是下面这个样子,earth.png被拉伸以充满整个屏幕:

直接使用QImage 显示

我们也可以直接使用QImage做显示,而不转换成QPixmap ,这要根据我们应用的具体需求来决定,如果需要的话我们可以这么写:

//correct, some times may be needed QImage image; image.load( ":/pics/earth.png" );   QPainter painter(this); painter.drawImage(0,0, image);

下面是显示效果(当然我们也可以对其进行缩放之后再显示)
从图片可以看出来它是按照原始尺寸显示earth.png的:

测试设备

本代码已通过在N97和N8上的测试。

本文转载自:http://developer.nokia.com/community/wiki/%E5%A6%82%E4%BD%95%E6%AD%A3%E7%A1%AE%E5%9C%B0%E5%9C%A8%E6%89%8B%E6%9C%BA%E4%B8%8A%E6%98%BE%E7%A4%BA%E5%9B%BE%E7%89%87%E2%80%94%E2%80%94QImage%E4%B8%8EQPixmap%E5%AE%8C%E5%85%A8%E8%A7%A3%E6%9E%90

此外,关于Qt绘图,还可以借鉴这篇文章:http://www.360doc.com/content/12/0717/14/1291795_224728691.shtml

http://blog.csdn.net/jan5_reyn/article/details/38959519

如何正确地在手机上显示图片——QImage与QPixmap完全解析的更多相关文章

  1. transform:rotate在手机上显示有锯齿的解决方案

    transform:rotate 属于简单好用的效果,但在手机上显示时,会有比较明显锯齿. 解决方案也很简单, 利用外层容器的overflow:hidden 加上图片margin:-1px 就可以解决 ...

  2. QImage与QPixmap完全解析

    转载自http://www.civilnet.cn/bbs/browse.php?topicno=4691 用Qt程序在手机上显示一幅图片对编程人员来说是再基础不过的一件事情了.那么先让大家看两段代码 ...

  3. IE浏览器中图片路径正确< img ... />标签不显示图片

    如下图所示,下面的html要去加载上面的jpg图片: 代码如下: <img src="luzhanshi1.jpg" alt="图片加载失败"> 使 ...

  4. Android 代码中文字在手机上显示乱码问题解决方法

    在学习Android过程中,用于测试时发现,代码中的中文在真机上会显示乱码, 网上查阅了些资料,参考如下: http://www.androidchina.net/3024.html http://b ...

  5. .Net语言 APP开发平台——Smobiler学习日志:如何在手机上显示类似EXCEL表格

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 样式一 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的&qu ...

  6. transform:rotate在手机上显示有锯齿的解决方案大全

    先来个兼容性说明,洗洗脑: div{transform:rotate(7deg);-ms-transform:rotate(7deg); /* IE 9 */-moz-transform:rotate ...

  7. Web页面在手机上显示过大问题

    网上抄来了,自己也备忘下:增加<meta name="viewport" content="width=device-width, initial-scale=1. ...

  8. pyqt pyside QLabel 显示图片

    pyqt pyside QLabel 显示图片 pixmap = QtGui.QPixmap("D:/myPicture.jpg") label.setPixmap(pixmap) ...

  9. InteractiveHtmlBom 在手机上无法显示 BOM List 和装配图的问题

    InteractiveHtmlBom 在手机上无法显示 BOM List 和装配图的问题 InteractiveHtmlBom 插件是一款用于 KiCad BOM 装配图生成插件. 最近新生成的 文件 ...

随机推荐

  1. zzbank oneOpencloud Env linuxaix6.1 interactiveMaintain(nfs,aix genintall基于系统iso光盘,aix6.1 puppet-Agent,Cent6.4 puppetServer,agent time no syn case Er)

    1,puppet--server,Client,Agent time no syn case eror puppet agent --server frontend -terr: Could not ...

  2. 第七届河南省赛10403: D.山区修路(dp)

    10403: D.山区修路 Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 69  Solved: 23 [Submit][Status][Web Bo ...

  3. eclipse编译错误

    ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2 JDWP exit error AGE ...

  4. android studio recent projects

    android studio正常的删除项目的方法是可以点击右键,选择project structure,进入到界面时,选择你要删除的工程,点击减号,接着就可以右键工程有一个delete. 另外一种方法 ...

  5. JavaEE Tutorials (9) - 运行持久化示例

    9.1order应用118 9.1.1order应用中的实体关系119 9.1.2order应用中的主键121 9.1.3实体映射到多个数据库表125 9.1.4order应用中的层叠操作125 9. ...

  6. kinect for windows - SkeletonBasics-D2D详解之一

    之前的文章介绍了深度图的获取,但是深度图只是提供了一些数据,这些数据给上层应用使用还是偏底层一些,我们希望在这个基础上,获取一些信息,比如手挥动,人跑步,或者运动等等,那么这个文章开始我们来讲述kin ...

  7. 基于Visual C++2013拆解世界五百强面试题--题5-自己实现strstr

    请用C语言实现字符串的查找函数strstr, 找到则返回子字符串的地址,没有找到返回为空,请用数组操作与指针操作实现 看到题目想到最简单的方法就是母字符串和子字符串比较,如果不同,将指向母字符串的指针 ...

  8. Shared_from_this 几个值得注意的地方

    shared_from_this()是enable_shared_from_this<T>的成员 函数,返回shared_ptr<T>.首先需要注意的是,这个函数仅在share ...

  9. SSH框架的简单学习—Structs学习

    一:struts部分 1.打开Myeclipse,创建一个web project,项目名称为SSHDemo. 2.在web的lib下粘贴struts2-blank.war解压后WEB-INF\lib下 ...

  10. Android JNI入门第五篇——基本数据类型使用

    前面讲到了java和native数据类型,这里就开始做一下使用: 第一步:新建工程 第二部:书写 java方法: public class NativeMethod { static { System ...