• Qt资源使用的方式


    目录

    一、概述

    二、qrc资源静态使用

    1、在qrc文件中加入图片

    2、qrc资源编译cpp文件

    3、资源的使用

    三、qrc资源动态使用

    1、概述

    2、资源注册和反注册源码

    3、使用方法

    四、I/O读取


    一、概述

            Qt资源体系采用平台独立机制来存储应用程序执行时的二进制文件。这种机制在应用程序需要一些确定的文件(图标、翻译文件等等)而且又不想冒丢失文件的风险时是有用的。资源体系依赖于 qmake, rcc (Qt’sresource compiler), 和 QFile 的紧密协作。Qt3 的 qembed 工具和  image 
    collection 机制被废除。

    二、qrc资源静态使用

    1、在qrc文件中加入图片

     2、qrc资源编译cpp文件

    1. /****************************************************************************
    2. ** Resource object code
    3. **
    4. ** Created: Sun Oct 23 19:57:12 2022
    5. ** by: The Resource Compiler for Qt version 4.8.4
    6. **
    7. ** WARNING! All changes made in this file will be lost!
    8. *****************************************************************************/
    9. #include <QtCore/qglobal.h>
    10. static const unsigned char qt_resource_data[] = {
    11. ...//省略了图片数据
    12. // D:/documents/visual studio 2010/Projects/testWidget/testWidget/test.png
    13. };
    14. static const unsigned char qt_resource_name[] = {
    15. // testWidget
    16. 0x0,0xa,
    17. 0x9,0xd0,0xf4,0x84,
    18. 0x0,0x74,
    19. 0x0,0x65,0x0,0x73,0x0,0x74,0x0,0x57,0x0,0x69,0x0,0x64,0x0,0x67,0x0,0x65,0x0,0x74,
    20. // test.png
    21. 0x0,0x8,
    22. 0xc,0xa7,0x58,0x7,
    23. 0x0,0x74,
    24. 0x0,0x65,0x0,0x73,0x0,0x74,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67,
    25. };
    26. static const unsigned char qt_resource_struct[] = {
    27. // :
    28. 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
    29. // :/testWidget
    30. 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2,
    31. // :/testWidget/test.png
    32. 0x0,0x0,0x0,0x1a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
    33. };
    34. QT_BEGIN_NAMESPACE
    35. extern Q_CORE_EXPORT bool qRegisterResourceData
    36. (int, const unsigned char *, const unsigned char *, const unsigned char *);
    37. extern Q_CORE_EXPORT bool qUnregisterResourceData
    38. (int, const unsigned char *, const unsigned char *, const unsigned char *);
    39. QT_END_NAMESPACE
    40. int QT_MANGLE_NAMESPACE(qInitResources_testwidget)()
    41. {
    42. QT_PREPEND_NAMESPACE(qRegisterResourceData)
    43. (0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
    44. return 1;
    45. }
    46. Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources_testwidget))
    47. int QT_MANGLE_NAMESPACE(qCleanupResources_testwidget)()
    48. {
    49. QT_PREPEND_NAMESPACE(qUnregisterResourceData)
    50. (0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
    51. return 1;
    52. }
    53. Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources_testwidget))

          对于这种方式:其是将所有的图片资源都转化成二进制数据,存放在一个静态数组中,而后放到应用程序中。所以:当程序执行时:所有图片都会一直在内存中,这杨虽然读取速度很快,但是很占用内存空间,对于一些内存有限的设备不是很适合。

            当编译时,其会将我们写的 name.qrc文件转换生成一个qrc_name.cpp的资源文件,我们可以自己看下这个生成的cpp文件,发现其中就是主要有三个static const数组。

                  qt_resource_data[]

                  qt_resource_name[]

                  qt_resource_struct[]

           这其中qt_resource_data[]中存放的就是图片的二进制数据。 qt_resource_name是图片资源的一些名字的数组。qt_resource_struct目前还没明白具体意思。

    1. #ifndef Q_CONSTRUCTOR_FUNCTION
    2. # define Q_CONSTRUCTOR_FUNCTION0(AFUNC) \
    3. static const int AFUNC ## __init_variable__ = AFUNC();
    4. # define Q_CONSTRUCTOR_FUNCTION(AFUNC) Q_CONSTRUCTOR_FUNCTION0(AFUNC)
    5. #endif
    1. #ifndef Q_CONSTRUCTOR_FUNCTION
    2. # define Q_CONSTRUCTOR_FUNCTION0(AFUNC) \
    3. static const int AFUNC ## __init_variable__ = AFUNC();
    4. # define Q_CONSTRUCTOR_FUNCTION(AFUNC) Q_CONSTRUCTOR_FUNCTION0(AFUNC)
    5. #endif

            Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources_testwidget))会定义一个全局静态变量调用qInitResources_testwidget这个函数,将数据注册到Qt内部中。同一应用程序下的不同模块,可以共享这个资源。

            使用这种方法时,由于图片资源一直在内存中,避免了I/O操作,从而加快了读取速度。但是却是以消耗内存为代价的。

    3、资源的使用

    1. QIcon Icon(":/testWidget/test.png");
    2. this->setWindowIcon(QIcon(":/testWidget/test.png"));

    三、qrc资源动态使用

    1、概述

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

            图片是一种资源,而在Qt中,对于资源的使用是有独特的方式的。一般来说:资源在内存中是用资源对象树来表示的,该树在程序启动时创建而对于资源而言:我们都是需要先将其加入到这棵树才能加载到内存中并被程序使用而将一个图片资源放到程序的资源对象树是用函数QResource::registerResource()来实现的。亦即:要将资源向这颗资源对象树进行注册,这样才对在系统中new创建这个资“叶子”。          

    2、资源注册和反注册源码

    1. bool QResource::registerResource(const QString &rccFilename, const QString &resourceRoot)
    2. {
    3. QString r = qt_resource_fixResourceRoot(resourceRoot);
    4. if(!r.isEmpty() && r[0] != QLatin1Char('/'))
    5. {
    6. qWarning("QDir::registerResource: Registering a resource [%s] must be rooted in an absolute path (start with /) [%s]",
    7. rccFilename.toLocal8Bit().data(), resourceRoot.toLocal8Bit().data());
    8. return false;
    9. }
    10. QDynamicFileResourceRoot *root = new QDynamicFileResourceRoot(r);
    11. if(root->registerSelf(rccFilename))
    12. {
    13. root->ref.ref();
    14. QMutexLocker lock(resourceMutex());
    15. resourceList()->append(root);
    16. return true;
    17. }
    18. delete root;
    19. return false;

         

    1. bool
    2. QResource::unregisterResource(const QString &rccFilename, const QString &resourceRoot)
    3. {
    4. QString r = qt_resource_fixResourceRoot(resourceRoot);
    5. QMutexLocker lock(resourceMutex());
    6. ResourceList *list = resourceList();
    7. for(int i = 0; i < list->size(); ++i)
    8. {
    9. QResourceRoot *res = list->at(i);
    10. if(res->type() == QResourceRoot::Resource_File)
    11. {
    12. QDynamicFileResourceRoot *root = reinterpret_cast<QDynamicFileResourceRoot*>(res);
    13. if(root->mappingFile() == rccFilename && root->mappingRoot() == r)
    14. {
    15. resourceList()->removeAt(i);
    16. if(!root->ref.deref())
    17. {
    18. delete root;
    19. return true;
    20. }
    21. return false;
    22. }
    23. }
    24. }
    25. return false;
    26. }

    3、使用方法

           这种方法的主要步骤为:

           (1)生成外部二进制资源文件。

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

           (3)在不需要时进行反注册。

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

          那我们可以用它来执行命令 rcc -binary name.qrc -o name.rcc  来把qrc资源文件转成rcc二进制资源文件。在程序初始化时将rcc文件注册一下即可。

    1. int main()
    2. {
    3. ...
    4.    QResource::registerResource(rcc文件路径);
    5. ...
    6. }

    四、I/O读取 

    QIcon("./bmp/name.png");
    1. QIcon::QIcon ( const QString & fileName )
    2. Constructs an icon from the file with the given fileName. The file will be loaded on demand.
    3. If fileName contains a relative path (e.g. the filename only) the relevant file must be found relative to the runtime working directory.
    4. The file name can be either refer to an actual file on disk or to one of the application's embedded resources. See the Resource System overview for details on how to embed images and other resource files in the application's executable.

        

  • 相关阅读:
    【多思路附源码】2023高教社杯 国赛数学建模C题思路 - 蔬菜类商品的自动定价与补货决策
    2022.11.25Extended Traffic LightOJ - 1074
    算法day27
    使用STM32CubeMX实现按下按键,电平反转
    生成对抗网络
    WPF打开对话框选择文件、选择文件夹
    用PyTorch轻松实现二分类:逻辑回归入门
    独立站引流新玩法
    Visual Studio 2022插件的安装及使用 - 编程手把手系列文章
    Node.js 入门教程 7 从命令行运行 Node.js 脚本 & 8 如何退出 Node.js 程序
  • 原文地址:https://blog.csdn.net/kupe87826/article/details/127480001