Qt主题原理

概述


网上对 Qt 主题介绍比较少,主要是我们在使用主题的过程中,都是Qt 默认加载,用户基本上不做干预,细心的同学可能已经发现,在不同的平台(Mac\Wiwndows\linux)运行Qt 程序,他们的外观会保持系统风格一致,这就是Qt主题的功劳。

1. 什么是Qt主题


在不同的平台下,通过加载不同的style,来给用户呈现不同的图形界面外观、样式、图标集等.

Qt 应用的风格主题有多种,支持包括Windows XP Style Widget Gallery(windowsXp风格)、Windows Style Widget Gallery(window风格)、Windows Vista Style Widget Gallery(window vista风格)、Macintosh Style Widget Gallery(mac风格)、GTK Style Widget Gallery(GTK风格)、Fusion Style Widget Gallery(fusion风格)共六种。

这些主题位于Qt的widget模块中,通过 application 提供的接口来进行设置,例如

QApplication::setStyle("windowsxp");
QApplication::setStyle(QStyleFactory::create("Fusion"));

2. Qt 主题实现不同样式的原理


我们知道,Qt 绘图采用QPainter系统,那么在不同的平台要绘制不同的风格样式,就需要不同的绘制代码,那么这些不同的绘制代码,放到不同的风格样式的类中,不同的平台加载对应的风格类,然后在控件中做统一调用就实现了这个功能。具体怎么做呢,通过部分代码来说明一下,拿QPushbutton举例。

我们想象的绘制一个按钮,肯定有drawText、drawRect 等等这些函数,但是在QPushButton中并没有,而是简单的调用了 drawControl 而在drawControl中又调用了 wstyle 的 drawControl

wstyle 就是上面提到的六种主题的基类,drawControl 是一个虚函数,通过多态的方式就调用到不同的主题中。 CE_PushButton 表示一个控件元素,一个控件有多个元素组成,具体可以在Qt 官网中查看,style 中绘制就不多介绍。

void QPushButton::paintEvent(QPaintEvent *)
{
    QStylePainter p(this);
    QStyleOptionButton option;
    initStyleOption(&option);
    p.drawControl(QStyle::CE_PushButton, option);
}
void QStylePainter::drawControl(QStyle::ControlElement ce, const QStyleOption &opt)
{
    wstyle->drawControl(ce, &opt, this, widget);
}

3. 创建自定义主题


可以通过创建自定义样式来为应用程序创建自定义外观。创建自定义样式有两种方法。在静态方法中,您要么选择现有的 QStyle 类,将其子类化,然后重新实现虚函数以提供自定义行为,要么从头开始创建整个 QStyle 类。在动态方法中,可以在运行时修改系统样式的行为提供自定义行为。Qt 插件系统可以将样式创建为插件。作为插件创建的样式在运行时由 Qt 本身作为共享对象加载。编译插件并将其放入 Qt 的plugins/styles目录中。现在有一个 Qt 可以自动加载的可插拔样式。要在现有应用程序中使用新样式,只需使用以下参数启动应用程序:./myapplication -style custom。详细使用方式见官方文档

4. 平台主题插件


除了以上主题插件意外,还有一个平台主题插件的东西,上面的主题负责界面样式的绘制,那么平台主题封装了一些特有的行为,例如双击间隔时间、拖拽触发举例、光标闪烁的时间等等,还封装了 一些系统对话框,例如文件、字体、颜色、消息对话框以及调色板,标准图标、字体等等。平台主题在linux 下有 gnome (gtk3)theme、kdetheme

另外,上面提到的六种主题在不同的平台下,自动加载不同的主题,也是平台主题实现的,例如当我们程序使用 xcb 作为后端的时候,在 xcbqpa 首先创建 QGenericUnixTheme,QGenericUnixTheme 再根据具体的桌面环境标识,创建对应的平台主题。例如ubuntu、xfce 等桌面环境都是使用 gtk 开发的,那么就会创建 qgtk3theme 、当桌面环境是 kde 的时候就会创建 kdetheme。如果都不是的话,那么默认为 QGenericUnixTheme 这个平台主题。最后由上面的平台主题插件,返回具体创建前面六种主题中的哪一个,例如 在 QGenericUnixTheme 中,返回 Fusion 和 Windows。也就是我们系统上,如果不加载 DTK 的库,默认就是 Fusion主题。如果是 kdetheme 默认就是 Oxygen 或者 breeze 主题,这些主题由 kde 实现,如果kde 没有实现,仍然是 fusion。可以在 QKdeTheme 类中查看这些设置。

QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
{
    switch (hint) {
    ..........
    case QPlatformTheme::StyleNames: {
        QStringList styleNames;
        styleNames << QStringLiteral("fusion") << QStringLiteral("windows");
        return QVariant(styleNames);
    }
    ..............
    return QPlatformTheme::themeHint(hint);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值