zoukankan      html  css  js  c++  java
  • Qt中如果通过QStyle自定义能够跨平台的界面控件

    我们经常会碰到需要定制界面控件的要求。如果只是在一个平台上,比如说你的控件只需要在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. };  
    11. QStyle* get_application_style(const QString& style_name)  
    12. {  
    13.     if( style_name == “windows”){  
    14.         return new MyQStyle<QWindowsXPStyle>;  
    15.     } else if( style_name == “mac”){  
    16.         return new MyQStyle<QMacStyle>;  
    17.     } …  
    18.     cerr ;  
    19. }  

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

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

  • 相关阅读:
    js 实现页面局部(或图片)放大功能(vue)
    momentjs 使用总结
    VUX的使用方法(以弹出框为例)
    vue alert插件(标题为图片)(自写)
    vue 五星评价插件
    ES6 学习笔记(基础)
    SVG
    纯 CSS 实现实心三角形和空心三角形
    selectedIndex和onchange事件
    DOM文档获取和简介
  • 原文地址:https://www.cnblogs.com/findumars/p/5034850.html
Copyright © 2011-2022 走看看