Qt:资源的使用方式

1059 篇文章 280 订阅

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;
   }

总起来说就是:一个程序所用的所有资源都是放到一颗资源对象树中的,当程序启动时该树便会自动创建,而当我们使用某个资源时:都需要实现将其向该树进行注册,当不需要时则需要进行反注册。

使用图片资源的方式

常用的使用图片资源的方式,主要有三种:

使用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,因为其中用了大量的图片,结果导致内存使用量超乎想象的大,后来就进行了优化,也就是用了下边提到的第二种方法。

手动进行注册

理论

 第一种方法相当于静态加载,但很多情况下我们更希望是动态加载,亦即:用到哪个资源才将该资源加载进来,而不用的则不加载。

上边第一种方法之 所以显示出静态加载的特性,这是由于系统一次性自动把所有图片资源都进行了注册,并且在程序运行过程中一直没有进行反注册才导致的。  如果我们可以自行决定:什么时候对那一部分图片资源进行注册?什么时候对哪一部分图片资源进行反注册。则显然我们可以手动控制整个资源在内存中的生存周 期!!

   这种方法的主要步骤为:

       ①:生成外部二进制资源文件。

       ②:在需要时将该资源向程序的资源对象树进行注册并使用。

       ③:在不需要时进行反注册。

      步骤①主要是用了Qt自带的一个工具:rcc.exe  (处于bin文件夹中)。这是Qt的一个资源编译器,其编译对象是qrc文件,而生成rcc二进制资源文件。

    那我们可以用它来执行命令 rcc -binary name.qrc -o name.rcc  来把qrc资源文件转成rcc二进制资源文件。

      而后在程序内部:当需要使用某一图片资源时:则直接调用

     QResource::registerResource(“name.rcc”)进行注册创建分配内存即可!  而不使用时候则调用反注册函数!!

 

 

 

直接I/O读取

 比如:  ptr->setStyleSheet("./bmp/name.png");

     这种方式我不怎么用,感觉I/O操作速度慢吧,所以一直没去深究。

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值