Qt中(图片)资源的三种使用方式
Qt中使用图片资源的方法有很多种,以前我一直分不清各种之间的区别和Qt相应的处理机制,后来遇到一些实际的问题,然后再加上查阅源码和资料,总算弄明白一些事情,但是本文仅仅是个人理解,如有错误之处请告诉我,大家一起进步。
图片是一种资源,而在Qt中,对于资源的使用是有其独特的方式的!
①:一般来说:资源在内存中是用资源对象树来表示的,该树在程序启动时创建。
②:而对于资源而言:我们都是需要先将其加入到这棵树中才能加载到内存中并被程序使用!!
③:而将一个图片资源放到程序的资源对象树中是用函数QResource::registerResource()来实现的。亦即:要将资源向这颗资源对象树进行注册,这样才对在系统中new创建这个资“叶子”。
对于这一点我们可以直接查看该函数的源码:
bool
QResource::registerResource(const QString &rccFilename, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
if(!r.isEmpty() && r[0] != QLatin1Char('/'))
{
qWarning("QDir::registerResource: Registering a resource [%s] must be rooted in an absolute path (start with /) [%s]",
rccFilename.toLocal8Bit().data(), resourceRoot.toLocal8Bit().data());
return false;
}
QDynamicFileResourceRoot *root = new QDynamicFileResourceRoot(r);
if(root->registerSelf(rccFilename))
{
root->ref.ref();
QMutexLocker lock(resourceMutex());
resourceList()->append(root);
return true;
}
delete root;
return false;
}
由上可见:主要就是先创建了一个资源内存对象,而后将其append到资源对象树上。
④:当我们不再使用某个图片资源时:当然希望其不再占用内存,此时需要释放delete它。这时要用QResource::unregisterResource()函数来进行反注册。此函数的作用就是在资源对象树中遍历找到代表该资源的节点,而后delete释放它。源码为:
bool
QResource::unregisterResource(const QString &rccFilename, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
QMutexLocker lock(resourceMutex());
ResourceList *list = resourceList();
for(int i = 0; i < list->size(); ++i)
{
QResourceRoot *res = list->at(i);
if(res->type() == QResourceRoot::Resource_File)
{
QDynamicFileResourceRoot *root = reinterpret_cast<QDynamicFileResourceRoot*>(res);
if(root->mappingFile() == rccFilename && root->mappingRoot() == r)
{
resourceList()->removeAt(i);
if(!root->ref.deref())
{
delete root;
return true;
}
return false;
}
}
}
return false;
}
总起来说就是:一个程序所用的所有资源都是放到一颗资源对象树中的,当程序启动时该树便会自动创建,而当我们使用某个资源时:都需要实现将其向该树进行注册,当不需要时则需要进行反注册。
========================================================================
下边说一下我常用的使用图片资源的方式,主要有三种:
1:使用qrc资源文件来加载。
对于这种方式:其是将所有的图片资源都转化成二进制数据,存放在一个静态数组中,而后放到应用程序中。所以:当程序执行时:所有图片都会一直在内存中,这杨虽然读取速度很快,但是很占用内存空间,对于一些内存有限的设备不是很适合。
系统转换的主要步骤为:
①:当编译时,其会将我们写的 name.qrc文件转换生成一个qrc_name.cpp的资源文件,我们可以自己看下这个生成的cpp文件,发现其中就是主要有三个static const数组。
qt_resource_data[]
qt_resource_name[]
qt_resource_struct[]
这其中qt_resource_data[]中存放的就是图片的二进制数据。而后边的两个数组我们猜测是做了一个图片名字到上边数据的映射,方便系统找到data中的二进制数据。
至于内部作用机制,有的资料上说是:当使用qrc资源文件时:系统会自动将所有的图片资源都向程序的资源对象树进行注册,并且当程序结束运行时再进行反注册。这也正好解释了为什么此种方法下图片资源会一直占用内存的原因。
使用这种方法时:由于图片资源一直在内存中,避免了I/O操作,从而加快了读取速度。但是却是以消耗内存为代价的。我做过一个project,因为其中用了大量的图片,结果导致内存使用量超乎想象的大,后来就进行了优化,也就是用了下边提到的第二种方法。
2:手动进行注册。
第一种方法相当于静态加载,但很多情况下我们更希望是动态加载,亦即:用到哪个资源才将该资源加载进来,而不用的则不加载。
上边第一种方法之 所以显示出静态加载的特性,这是由于系统一次性自动把所有图片资源都进行了注册,并且在程序运行过程中一直没有进行反注册才导致的。 如果我们可以自行决定:什么时候对那一部分图片资源进行注册?什么时候对哪一部分图片资源进行反注册。则显然我们可以手动控制整个资源在内存中的生存周 期!!
这种方法的主要步骤为:
①:生成外部二进制资源文件。
②:在需要时将该资源向程序的资源对象树进行注册并使用。
③:在不需要时进行反注册。
步骤①主要是用了Qt自带的一个工具:rcc.exe (处于bin文件夹中)。这是Qt的一个资源编译器,其编译对象是qrc文件,而生成rcc二进制资源文件。
那我们可以用它来执行命令 rcc -binary name.qrc -o name.rcc 来把qrc资源文件转成rcc二进制资源文件。
而后在程序内部:当需要使用某一图片资源时:则直接调用
QResource::registerResource(“name.rcc”)进行注册创建分配内存即可! 而不使用时候则调用反注册函数!!
--》为了进行验证,我曾经测试了一个例子,主要思路就是:在一个工程中写了一个包含若干幅图片的qrc资源文件,将其转化成rcc二进制资源文件。 我在程序界面上摆放两个按钮button, 其中一个button的click事件响应槽负责调用QResource::registerResource()将这个二进制资源文件注册, 而另外一个button进行反注册。 然后跑一下这个程序,查看下其所占用的内存大小:
刚启动时:程序所占内存显示为:8940K

而后按下第一个button进行注册,此时占用内存为:9276K

最后点一下另外一个button,进行反注册后,其占用内存大小为:8948K

由上测试可见:注册后才会让资源占用内存!!反注册后其会从内存中delete掉!!
所以:这种方式算是动态加载,会少占用内存。但是如果图片过多的话,什么时候需要加载,什么时候需要去掉,这些逻辑就需要十分注意了。
3:直接I/O读取。
比如: ptr->setStyleSheet("./bmp/name.png");
这种方式我不怎么用,感觉I/O操作速度慢吧,所以一直没去深究。道理上边都有。
http://www.cnblogs.com/lzjsky/archive/2012/08/20/2647471.html
Qt中(图片)资源的三种使用方式的更多相关文章
- MyEclipse中web服务器的三种配置方式
初学Javaweb开发的人们都会遇到一个问题,就是服务器环境的搭建配置问题.下面介绍三种服务器的搭建方式. 直接修改server.xml文件 当你写了一个web应用程序(jsp/servlet),想通 ...
- Java中List集合的三种遍历方式(全网最详)
List集合在Java日常开发中是必不可少的,只要懂得运用各种各样的方法就可以大大提高我们开发的效率,适当活用各种方法才会使我们开发事半功倍. 我总结了三种List集合的遍历方式,下面一一来介绍. 首 ...
- iOS中图片动画的三种模式及基本的代码实现
-(void)play { //第一种图片动画模式 头尾方式 //头尾方式 [UIView beginAnimations:nil context:nil];//动画开始 [UIView setAni ...
- SpringMVC 拦截器不拦截静态资源的三种处理方式
SpringMVC提供<mvc:resources>来设置静态资源,但是增加该设置如果采用通配符的方式增加拦截器的话仍然会被拦截器拦截,可采用如下方案进行解决: 方案一.拦截器中增加针对静 ...
- spring mvc:拦截器不拦截静态资源的三种处理方式
方案一.拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml) <mvc:resources location="/" mapping="/**/* ...
- SpringMVC 拦截器不拦截静态资源的三种处理方式方法
方案一.拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml) <mvc:resources location="/" mapping="/**/* ...
- AngularJs中关于ng-class的三种使用方式说明
在开发中我们通常会遇到一种需求:一个元素在不同的状态需要展现不同的样子. 而在这所谓的样子当然就是改变其css的属性,而实现能动态的改变其属性值,必然只能是更换其class属性 这里有三种方法: 第一 ...
- java中进程与线程--三种实现方式
一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程:进程是指 ...
- oracle中if/else的三种实现方式
1.标准sql规范 .单个IF IF v=... THEN END IF; .IF ... ELSE IF v=... THEN ELSE t....; END IF; .多个IF IF v=... ...
随机推荐
- Java基础学习总结(49)——Excel导入导出工具类
在项目的pom文件中引入 <dependency> <groupId>net.sourceforge.jexcelapi</groupId> <artifac ...
- C++开源码项目汇总
Google的C++开源码项目 v8 - V8 JavaScript Engine V8 是 Google 的开源 JavaScript 引擎. V8 採用 C++ 编写,可在谷歌浏览器(来自 G ...
- TCP的可靠传输机制(简单好理解:分段与流,滑窗,连接,流量控制,重新发送,堵塞控制)
TCP的几大模块:分段与流,滑窗,连接,流量控制,重新发送,堵塞控制. 1.checksum:在发送TCP报文的时候,里面的信息可能会因为环境的问题,发送变化,这时,接收信号的时候就需要通过check ...
- php gettext方式实现UTF-8国际化多语言(i18n)
php gettext方式实现UTF-8国际化多语言(i18n) 一.总结 一句话总结: 二.php gettext方式实现UTF-8国际化多语言(i18n) 近 来随着i18n(国际化)的逐渐标准化 ...
- Microsoft Bot Framework 链接至微信公共号
如何将 Microsoft Bot Framework 链接至微信公共号 说到 Microsoft Bot Framework 其实微软发布了已经有一段时间了,有很多朋友可能还不太了解,微软Bot ...
- linux目录架构及常用的基本命令
linux目录架构 / 根目录 /bin 常用的命令 binary file 的目錄 /boot 存放系统启动时必须读取的档案,包括核心 (kernel) 在内 /boot/g ...
- 硬件——STM32 , SN74HC573锁存器
74HC573是一款高速CMOS器件: 上图中:输出使能为:OE 锁存使能为:LE 典型电路: 上图中:PWR-AL-0,PWR-AL-1,PWR-AL-2:是单片机输出的高低电平给573 对应的 ...
- [Maven实战](6)仓库(本地仓库,远程仓库,镜像)
1. 简单介绍 maven能够在某个位置统一存储全部maven项目共享的构件,这个统一的位置就是仓库.实际的Maven项目将不会各自存储其依赖文件,它们仅仅须要声明这些依赖的坐标,在须要的时候(比如. ...
- 解读Java中BigDecimal.ZERO.compareTo()的返回值含义
Java compareTo() 用法 例如: public static void main(String[] args) { BigDecimal bnum1, bnum2; bnum1 ...
- jboss-as-7.1.1.Final与jdk1.8不兼容解决方案
今天在安装1.8电脑上装了jboss7.1.1,配置好了运行的时候就是无法启动,最后得出答案是:jboss-as-7.1.1.Final与jdk1.8不兼容 1.如果你的电脑安装了jdk1.8,那么在 ...