应用需求:

提供皮肤切换选项,在不重启应用程序的情况下实现皮肤的动态切换。

理论基础:

1) 图片资源是如何被利用的

这里先简要说明一下实现原理,皮肤的动态切换其关键在于图片资源的加载方式。QT中每个应用程序启动后都会维护属于自己的资源子库,所有的图片以及UI资源都实现编译到rcc文件中,而rcc文件是整合了所有资源的二进制文件,这种方式属于动态加载。

图片是一种资源,在QT中,对于资源的使用有以下几点:

1>  一般来说:资源在内存中是用资源对象树来表示的,该树在程序启动时创建。

2>    对于资源而言:都是需要先将其加入到这棵树中才能加载到内存中并被程序使用。

3>    将一个图片资源动态加载到资源的对象树中是用函数:QResource::registerResource()来实现的,即先将资源向这颗资源对象树进行注册,这样才可以在程序中使用该资源叶子。资源一旦注册到资源子树中它就会占用内存。

4>    当不再需要使用某个资源图片时,我们不希望它继续占用内存,此时需要用QResource::unregisterResource()来进行反注册。此函数的作用就是在资源对象树中遍历找到代表该资源的节点,然后delete释放它。

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

2) 图片资源使用的三种方式

1>  在程序运行时加载图片

这是最简单的一种使用方法,例如:image = newQImage(“1.png”),这种方法在程序运行时再去加载图片,需要在对应目录下事先放置好图片,这样做的优点是程序 运行时不需要的文件不会加载,节省了内存,但是这种方式是I/O读取,因此速度会相对慢一些。

2>  将图片编译进工程

这种方式是在pro文件下添加一行:RESOURCES = test.qrc ; qrc文件中添加了对图片资源的引用,它的格式如下:

这样程序在发布时不需要在目录下放置图片,利用该qrc文件在编译的时候会自动生成qrc_test.cpp文件,里面主要是利用三个数组来存放图片的二进制数据。

当使用qrc资源文件时,系统会自动将所有的图片资源都向程序的资源对象树进行注册,并且当程序结束时再进行反注册。使用这种方式,由于图片资源一直在内存中,避免了I/O操作,加快了读取速度,但是却是以消耗内存为代价的。

3>  手动进行注册

上面利用qrc文件是程序运行时一次性将图片资源全部加载到资源对象树中,直到程序运行结束才会反注册。而最佳的实现方式是:需要用到时,将资源加载进来,不需要的时候可以对资源进行反注册,从而可以节省内存。

这种方法的主要步骤为:

1)    利用qrc和qss文件生成rcc二进制资源文件:rcc.exe –binary test.qrc –o test.rcc

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

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

皮肤插件系统的实现:

皮肤插件系统实现的基本逻辑图如下:

其实现原理就是根据上面的三种方式,手动进行rcc文件的注册与反注册。这里需要强调的一点是:每个模块都有自己的一套:qrc、qss以及他们生成的rcc文件,因为我们利用rcc文件就是避免它一次性将所有的资源注册上(如果每套皮肤只用一个rcc文件将所有的资源都注册上,在内存方面没有优势,只是提供了可以进行皮肤动态切换的可能,GF2中的每套皮肤就只有一个rcc文件),需要时注册,不需要时反注册,因此我们需要手动地控制哪个模块合适注册、何时反注册。比如:程序启动先注册login模块的资源文件,当登录成功后,登录界面就消失了,然后主面板开始出现,这个时候我们就可以将登录模块注册的资源文件进行反注册。如果主界面逻辑中还有一个按钮是显示所有文件同步信息的,当我们点击时,文件信息模块注册上,关闭窗口时,文件信息模块资源反注册,而此时主面板模块资源一直都是注册着的。采用这种方式,可能会花费一些精力还处理不同模块资源的注册与反注册。

总结:

这里的关键还是要理解动态方式使用rcc文件,它是插件系统得以实现的基础,本质就是向资源对象树中的注册与反注册。注意:这里充分利用了配置文件的优点,还是基于插件的体系。由于界面具体的样式还没有细调,这里就不上图了,不过已经可以实现皮肤的动态切换了。联想到其它,所有皮肤切换的实现原理都基本相似吧,自己的知识盲区中又少了一块,加油!!五一来临。

QT皮肤系统的动态切换的更多相关文章

  1. Qt 国际化之二:多国语界面动态切换的实现

    第一步在你的pro里面加入 TRANSLATIONS = myexec_zh.ts (根据对应的ts文件修改)第二步用lupdate 操作pro 将要翻译的提取到ts文件 命令是 lupdate my ...

  2. Ext Js 6+ 动态切换皮肤

    在这里以ext js 6.2.1版本为例(注:需要安装Sencha Cmd,以及下载对应的sdk) 1.创建空白项目 在命令行中输入sencha -sdk D:\Code\ext-6.2.1 gene ...

  3. ionic动态切换主题皮肤

    本来想通过css自定义属性值: :root{ --red:red; } p{ color:var(--red); } div{ background:var(--red); } 在ionic2设置动态 ...

  4. Silverlight4中实现Theme的动态切换

    Silverlight一般用来开发一些企业的应用系统,如果用户一直面对同一种风格的页面,时间长了难免厌烦,所以一般都会提供好几种风格及Theme供用户选中,下面就来说一下如何在不重新登录系统的情况下, ...

  5. QT皮肤框架-TQUI

    本皮肤框架的相关文档,请在附件中下载,包括测试程序源码,帮助文档.相关文档可到我的百度网盘中下载,或者在本贴附件中下载. 百度网盘地址:TQUI-V1.0项目说明及测试程序源码 项目更新说明:---- ...

  6. Qt Quick 组件和动态创建的对象具体的解释

    在<Qt Quick 事件处理之信号与槽>一文中介绍自己定义信号时,举了一个简单的样例.定义了一个颜色选择组件,当用户在组建内点击鼠标时,该组件会发出一个携带颜色值的信号,当时我使用 Co ...

  7. hibernate动态切换数据源

    起因: 公司的当前产品,主要是两个项目集成的,一个是java项目,还有一个是php项目,两个项目用的是不同的数据源,但都是mysql数据库,因为java这边的开发工作已经基本完成了,而php那边任务还 ...

  8. Spring动态切换多数据源解决方案

    Spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性.而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时 ...

  9. 【原】通过AOP实现MyBatis多数据源的动态切换

    [环境参数]1.开发框架:Spring + SpringMVC + MyBatis 2.数据库A的URL:jdbc.url=jdbc:mysql://172.16.17.164:3306/ test? ...

随机推荐

  1. [转]HTTP Error 400. The request hostname is invalid.

    一般看到网站提示Bad Request(Invalid Hostname)错误我们都会说是iis,apache出问题了,iis出现这种问题解决办法大概是:IIS> 默认网站> > 属 ...

  2. [Jquery] js获取浏览器滚动条距离顶端的距离

    需要用js获取滚动条距离窗口顶端的距离和js获取浏览器可视化窗口的大小  一.jQuery获取的相关方法 jquery 获取滚动条高度 获取浏览器显示区域的高度 : $(window).height( ...

  3. 【转载】ASP.NET获取路径的方法

    HttpContext.Current.Request.PhysicalPath;    // 获得当前页面的完整物理路径.比如 F:\XFU.NSQS\project\website\Default ...

  4. Server-Side Access Control

    Firefox 3.5 implements the W3C Access Control specification.  As a result, Firefox 3.5 sends specifi ...

  5. SEH and C++ Exceptions,自定义CSeException

    Description of CSeException CSeException class is based on CException class provided by MFC. I overw ...

  6. 【HDOJ】3487 Play with Chain

    Splay入门题目,区间翻转,区间分割. /* */ #include <iostream> #include <string> #include <map> #i ...

  7. Android 写文件到手机

    1)// 在手机中创建文件 FileOutputStream phone_outStream =this.openFileOutput("1.txt", Context.MODE_ ...

  8. Grading

    100 >= A >= 93 > A- >= 90; 90 > B+ >= 87 > B >= 83 > B- >= 80; 80 > ...

  9. Ubuntu下安装mysql-python包

      sudo apt-get install libmysqld-dev sudo apt-get install libmysqlclient-dev sudo apt-get install py ...

  10. [并发编程]使用线程安全队列和条件变量的notify来安排分步骤任务

    // 方法1:直接构建N个THread来run foreach (i, size) { thread trd(&Instance::doWork, &inst); lstTrd.pus ...