QT皮肤系统的动态切换
应用需求:
提供皮肤切换选项,在不重启应用程序的情况下实现皮肤的动态切换。
理论基础:
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皮肤系统的动态切换的更多相关文章
- Qt 国际化之二:多国语界面动态切换的实现
第一步在你的pro里面加入 TRANSLATIONS = myexec_zh.ts (根据对应的ts文件修改)第二步用lupdate 操作pro 将要翻译的提取到ts文件 命令是 lupdate my ...
- Ext Js 6+ 动态切换皮肤
在这里以ext js 6.2.1版本为例(注:需要安装Sencha Cmd,以及下载对应的sdk) 1.创建空白项目 在命令行中输入sencha -sdk D:\Code\ext-6.2.1 gene ...
- ionic动态切换主题皮肤
本来想通过css自定义属性值: :root{ --red:red; } p{ color:var(--red); } div{ background:var(--red); } 在ionic2设置动态 ...
- Silverlight4中实现Theme的动态切换
Silverlight一般用来开发一些企业的应用系统,如果用户一直面对同一种风格的页面,时间长了难免厌烦,所以一般都会提供好几种风格及Theme供用户选中,下面就来说一下如何在不重新登录系统的情况下, ...
- QT皮肤框架-TQUI
本皮肤框架的相关文档,请在附件中下载,包括测试程序源码,帮助文档.相关文档可到我的百度网盘中下载,或者在本贴附件中下载. 百度网盘地址:TQUI-V1.0项目说明及测试程序源码 项目更新说明:---- ...
- Qt Quick 组件和动态创建的对象具体的解释
在<Qt Quick 事件处理之信号与槽>一文中介绍自己定义信号时,举了一个简单的样例.定义了一个颜色选择组件,当用户在组建内点击鼠标时,该组件会发出一个携带颜色值的信号,当时我使用 Co ...
- hibernate动态切换数据源
起因: 公司的当前产品,主要是两个项目集成的,一个是java项目,还有一个是php项目,两个项目用的是不同的数据源,但都是mysql数据库,因为java这边的开发工作已经基本完成了,而php那边任务还 ...
- Spring动态切换多数据源解决方案
Spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性.而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时 ...
- 【原】通过AOP实现MyBatis多数据源的动态切换
[环境参数]1.开发框架:Spring + SpringMVC + MyBatis 2.数据库A的URL:jdbc.url=jdbc:mysql://172.16.17.164:3306/ test? ...
随机推荐
- [转]HTTP Error 400. The request hostname is invalid.
一般看到网站提示Bad Request(Invalid Hostname)错误我们都会说是iis,apache出问题了,iis出现这种问题解决办法大概是:IIS> 默认网站> > 属 ...
- [Jquery] js获取浏览器滚动条距离顶端的距离
需要用js获取滚动条距离窗口顶端的距离和js获取浏览器可视化窗口的大小 一.jQuery获取的相关方法 jquery 获取滚动条高度 获取浏览器显示区域的高度 : $(window).height( ...
- 【转载】ASP.NET获取路径的方法
HttpContext.Current.Request.PhysicalPath; // 获得当前页面的完整物理路径.比如 F:\XFU.NSQS\project\website\Default ...
- Server-Side Access Control
Firefox 3.5 implements the W3C Access Control specification. As a result, Firefox 3.5 sends specifi ...
- SEH and C++ Exceptions,自定义CSeException
Description of CSeException CSeException class is based on CException class provided by MFC. I overw ...
- 【HDOJ】3487 Play with Chain
Splay入门题目,区间翻转,区间分割. /* */ #include <iostream> #include <string> #include <map> #i ...
- Android 写文件到手机
1)// 在手机中创建文件 FileOutputStream phone_outStream =this.openFileOutput("1.txt", Context.MODE_ ...
- Grading
100 >= A >= 93 > A- >= 90; 90 > B+ >= 87 > B >= 83 > B- >= 80; 80 > ...
- Ubuntu下安装mysql-python包
sudo apt-get install libmysqld-dev sudo apt-get install libmysqlclient-dev sudo apt-get install py ...
- [并发编程]使用线程安全队列和条件变量的notify来安排分步骤任务
// 方法1:直接构建N个THread来run foreach (i, size) { thread trd(&Instance::doWork, &inst); lstTrd.pus ...