我们经常会碰到需要定制界面控件的要求。如果只是在一个平台上,比如说你的控件只需要在Windows上显示,那很好办,Hard code 你的look and feel就可以了。但是如果界面需要在不同平台上显示native的界面风格,比如在Windows上就是Windows的风格,Mac上就是Mac的风 格,难道需要为每个平台写不同的代码吗?另外,如果是在Qt这个平台上你需要修改整体的界面风格,同时你的程序也需要跨平台,那你可能需要为每个平台派生 该平台下的QStyle对象(Windows上有QWindowsXPStyle,QVistaStyle,Mac上有QMacStyle,等等)。同样 修改之后也需要将修改应用到其他平台上。有更好的解决方案吗?

回答是肯定的。 首先你可以参照这篇有点老的文章“http://doc.trolltech.com/qq/qq09-q-and-a.html#style ”,使用Proxy Pattern来实现。创建一个Proxy,然后定义一个指向当前平台的style实例,这样就可以很容易的做一些定制。不过创建Proxy的过程可能有 一些繁琐,后期也需要根据QStyle的更新进行维护。Proxy是一个在Qt中使用的非常广泛的pattern,如果你对proxy pattern不熟悉的话,可以去Wiki上看看简要的说明。当然这种方法也存在一些问题。其中最大的一个问题,当调用被代理style的函数时,比如 MyProxyStyle::DrawControl会去调用QWindowXPStyle::DrawControl,但是在DrawControl返 回之前,后者永远只会调用QWindowXPStyle里面的函数,那我Proxy中customize的行为是得不到调用的。其实这个问题一直都是存在 的,现在依然存在。那如何解决呢?

方案1:依然使用Proxy模式, 比如“这里 ”提供的方法。假设现在的需求是:为所有快捷方式显示下划线。方法如下:

首先创建一个PorxyStyle,不过不是QStyle的子类。是不是认为这样错了呢?怎么可能创建新的Style但是不从QStyle派生,那有多少工作需要做啊?不过请耐心往下看。ProxyStyle的代码如下:

  1. class ProxyStyle
  2. {
  3. public:
  4. ProxyStyle(const QString &baseStyle) { style = QStyleFactory::create(baseStyle); }
  5. int proxyStyleHint(QStyle::StyleHint hint, const QStyleOption *option = 0,
  6. const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const
  7. {
  8. if (hint == QStyle::SH_UnderlineShortcut)
  9. return 1;
  10. return style->styleHint(hint, option, widget, returnData);
  11. }
  12. private:
  13. QStyle *style;
  14. };

然后这么我们真正自定义的Style这样来实现:

  1. #define ADDSTYLESUBCLASS(BaseStyleClass, BaseStyleName)
  2. class My##BaseStyleClass : public BaseStyleClass, public ProxyStyle
  3. {
  4. public:
  5. My##BaseStyleClass() : BaseStyleClass(), ProxyStyle(BaseStyleName) {}
  6. int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const
  7. {
  8. return proxyStyleHint(hint, option, widget, returnData);
  9. }
  10. };

这样你可以通过下面的宏来简单的实现对不同平台Sytle的定义,如果下次Windows 7的Style出现自了Qt中,你只需要加上一行代码便能解决所有的问题:

  1. ADDSTYLESUBCLASS(QCleanlooksStyle, "cleanlooks");
  2. ADDSTYLESUBCLASS(QPlastiqueStyle, "plastique");
  3. ADDSTYLESUBCLASS(QMotifStyle, "motif");
  4. ADDSTYLESUBCLASS(QWindowsStyle, "windows");
  5. ADDSTYLESUBCLASS(QCDEStyle, "cde");

方案2:“动态”继承

动态继承的方法很简单,相信你看到会眼前一亮。主要是利用模板的特性。可以这样来写你的新的Style:

  1. template<typename T>
  2. class MyQStyle : public T
  3. {
  4. public:
  5. MyQStyle() : T() {}
  6. ~MyQStyle() {}
  7. virtual void drawItemText(…) { … }
  8. virtual int pixelMetric(…) { … }
  9. };
  10. QStyle* get_application_style(const QString& style_name)
  11. {
  12. if( style_name == “windows”){
  13. return new MyQStyle<QWindowsXPStyle>;
  14. } else if( style_name == “mac”){
  15. return new MyQStyle<QMacStyle>;
  16. } …
  17. cerr ;
  18. }

看到了吧,是不是很方便啊?动态继承没有使用proxy,因此减少了很多不必要的代码,但是同时动态继承也有其缺点:它必须通过模板部分特例话的方 法来处理不同的QWindowsXPStyle,QMacStyle中不同的函数名带来的编译问题。不过我还是很倾向于动态继承的方法。

http://www.cnblogs.com/SkylineSoft/articles/2046272.html

Qt中如果通过QStyle自定义能够跨平台的界面控件的更多相关文章

  1. 【C#】自定义容器控件,设置界面控件,支持设计器拖入控件

    先上效果图: 1.先重写设置界面的控件功能: public partial class SetterControl : UserControl { public SetterControl() { I ...

  2. MFC中 自定义类访问主对话框控件的方法

    之前一直在找有木有好点的方法.现在终于被我找到,收藏之~~~~~~ 在使用mfc的时候经常遇到自定义类访问主对话框控件的问题,例如自定义类中的方法要输出一段字符串到主对话框的EDIT控件.控制对话框的 ...

  3. Android 自定义View之自绘控件

    首先要提前声明一下,我对于自定义View的理解并不是很深,最近啃了几天guolin博主写的关于自定义View的博客,讲的非常棒,只不过涉及到源码和底层的一些东西,我自己就懵逼了,目前只是会了关于自定义 ...

  4. [Swift通天遁地]九、拔剑吧-(3)创建多种自定义Segment分段样式的控件

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  5. asp.net mvc中使用jquery H5省市县三级地区选择控件

    地区选择是项目开发中常用的操作,本文讲的控件是在手机端使用的选择控件,不仅可以用于实现地区选择,只要是3个级别的选择都可以实现,比如专业选择.行业选择.职位选择等.效果如下图所示: 附:本实例asp. ...

  6. DELPHI中如何让FORM窗体透明,只显示控件?

    DELPHI中如何让FORM窗体透明,只显示控件?分享到: 对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理 回复次数:7largewanglargewanglargewang等级:Blank ...

  7. QT_5_ Qt中信号和槽 + 自定义信号和槽 + lambda 表达式

    1.Qt中信号和槽 1.1 需求:点击按钮关闭窗口 1.2 利用connect进行链接 1.3 参数1 信号发送者(指针) 参数2 发送的信号(信号地址) 参数3 信号的接受者(指针) 参数4 处理槽 ...

  8. 如何获得 Qt窗口部件在主窗口中的位置--确定鼠标是否在某一控件上与在控件上的位置

    用Qt Creator 设计程序时,最方便的就是ui设计器,可以很容易的得到想要的布局. 但是这样自动布局带来的后果是很难知道窗口中某一部件在主窗口中的相对位置. 在处理子窗口鼠标事件时变的很麻烦.主 ...

  9. Qt make clickable label 制作可点击的Label控件

    Qt中的Label标签控件的作用绝不仅仅限于显示静态文本,其实它的功能很强大,由于其有setPixmap()成员函数,故而可以当显示图片窗口使用,而且还可以实时显示摄像头捕获的图片,然后它对鼠标事件的 ...

随机推荐

  1. PHP性能如何实现全面优化?

    性能是网站运行是否良好的关键因素, 网站的性能与效率影响着公司的运营成本及长远发展,编写出高质高效的代码是我们每个开发人员必备的素质,也是我们良好的职业素养. 如何优化PHP性能呢? 一.变量(重要) ...

  2. php7 install memcache extension

    #download source code package from git $ git clone https://github.com/websupport-sk/pecl-memcache.gi ...

  3. PHP基础示例:用正则表达式修改配置信息

    各php工作原理图: 以下是扯代码时间: <?php //配置文件信息 define("HOST","localhost"); //主机名 define( ...

  4. Windows 下 Python easy_install 的安装

    下载安装python安装工具 下载地址:http://pypi.python.org/pypi/setuptools 可以找到正确的版本进行下载.win7 32位可以下载setuptools-0.6c ...

  5. Extjs springmvc session 超时 处理

    如果你的项目使用ExtJS作为表现层,你会发现,SESSION超时控制将是一个问题.本文将就自己的经验,来解决这一问题,当然,解决问题并非只有一种方法,我只是提出我的方法.首先,做超时控制,必需使用过 ...

  6. javascript 多行字符串

    javascript 字符串多行 平时一般使用 字符串+,或者[].join('')的方式 同事推荐了这样的形式 ExceptionDivHtml="<div class='gameI ...

  7. Octopress创建GitHub Pages——基于代码托管的静态博客

    Github Pages是静态网页来的,官方也半认可了它的博客用途,代码挂在github上,随时都可以更改,算是不错的一种尝试,因为它是静态的,所以在表现上会自由得多,但是,同样因为它是静态的,管理上 ...

  8. ThinkPHP中ajax提交数据

    最近在做项目时遇到了一些需要从页面用ajax提交数据到后台的操作,无奈本人技术有限,网上苦寻,研究了一下ajax和thinkPHP的结合,黄天不负苦心人,终于搞定了. 闲话少叙,进入正题:我需要从页面 ...

  9. log4j.xml 为什么要使用SLF4J而不是Log4J

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SY ...

  10. 04737_C++程序设计_第5章_特殊函数和成员

    例5.1 分析下面程序中析构函数与构造函数的调用顺序. #include<iostream> using namespace std; class object { private: in ...