`
tomhibolu
  • 浏览: 1431052 次
文章分类
社区版块
存档分类
最新评论

Qt stylesheet 源码学习

 
阅读更多

stylesheet

本文不准备谈样式表的使用。因为Manual中介绍的很清楚了,给的例子也都很不错。再就是我本身对CSS语法不太熟,术语把握不好,qss用的不多。

不过,有两个问题新手似乎特容易迷惑,简单提一下:

QWidget直接派生类的样式表不起作用

典型的表述(之一)是,从QWidget派生一个窗口,使用stylesheet设置背景,在designer中可以看到效果,编译运行后,没有背景。

该怎么办呢?对此Manual中专门有强调,摘录如下:

If you subclass from QWidget, you need to provide a paintEvent for your custom QWidget as below:
 void CustomWidget::paintEvent(QPaintEvent *)
 {
     QStyleOption opt;
     opt.init(this);
     QPainter p(this);
     style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
 }

原因比较简单,QWidget的paintEvent()是空的,而样式表要通过paint被绘制到窗口中。

设置样式表后,其所有的子Widget也都跟着变了

遇到这种问题的,通常都是尝试给窗口这是背景图片,结果发现:所有的子widget也被单独设置背景图片。

这个主要是大家都不熟悉CSS用法导致的,设置样式表对哪些内容有效。是通过选择器进行控制的。

而如果不设置选择器,比如

w.setStyleSheet("background-image: url(:/dbzhang800.png);");

这其实是不符合CSS语法的,会被转换成

w.setStyleSheet("*{background-image: url(:/dbzhang800.png);}");

这样一来,使用了“通用选择器”,所有的子widget也就均被应用了该样式

stylesheet 与 QStyle

简单看看看点二者的异同。

使用

  • 可以对整个应用程序 或 某个widget设置 样式(QStyle)
    • 通过命令行 -style xxx
    • QApplication::setStyle()
    • QWidget::setStyle()
  • 也可以对整个应用程序 或 某个widget设置样式表(stylesheet)
    • 通过命令行 -stylesheet xxx
    • QApplication::setStyleSheet()
    • QWidget::setStyleSheet()

注意点:

  • 如果你对某个widget设置QStyle,那么该样式只对该widget有效,其子widget不受影响;但如果设置样式表,那么所有的子widget会继承该样式表。

关联

无论设置样式还是样式表,都会注意到一个QStyleSheetStyle存在。

当我们为应用程序或widget设置样式表时,Qt会将其样式设置为QStyleSheetStyle

void QWidget::setStyleSheet(const QString& styleSheet)
{
...
    d->extra->styleSheet = styleSheet;
...
    d->setStyle_helper(new QStyleSheetStyle(...), true);
...
}

而在有样式表存在的情况下,通过setStyle()设置的样式时:

void QWidget::setStyle(QStyle *style)
{
...
    d->setStyle_helper(new QStyleSheetStyle(style), true);
}

这时,如果通过style()获取样式,将不是setStyle()中参数指定的那个样式,而是这个QStyleSheetStyle的实例(当然,这二者是有关系的,代理关系)。

QStyleSheetStyle

这是一个私有类,但从名字上可以猜出:

  • 它是QStyle的派生类
  • 和 stylesheet 有关

首先:它是QStyle的派生类,同时构造函数接受另一个QStyle作为参数

class QStyleSheetStyle : public QWindowsStyle
{
    Q_OBJECT
public:
    QStyleSheetStyle(QStyle *baseStyle);
    ~QStyleSheetStyle();
...

其次:它要解析设置在应用程序、它的父对象、或者自身安装的样式表

QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
{
...
    QStyleSheetStyleSelector styleSelector;
...
    //获取“默认”样式设置,在
    styleSelector.styleSheets += getDefaultStyleSheet();
...
    //获取应用程序的样式设置,注意:如果以file:///开头,则按照文件解析
    if (!qApp->styleSheet().isEmpty()) {
        StyleSheet appSs;
        QString ss = qApp->styleSheet();
        if (ss.startsWith(QLatin1String("file:///")))
                ss.remove(0, 8);
        parser.init(ss, qApp->styleSheet() != ss);
        parser.parse(&appSs)
        styleSelector.styleSheets += appSs;
    }
...
    //依次逐级向上查找各个父窗口安装的样式表,注意,如果样式表没有设置选择器,它会自动设置为 “*”
    QVector<QCss::StyleSheet> widgetSs;
    for (const QWidget *wid = w; wid; wid = parentWidget(wid)) {
        if (wid->styleSheet().isEmpty())
            continue;
        StyleSheet ss;
        parser.init(wid->styleSheet());
        if (!parser.parse(&ss)) {
            parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1Char('}'));
        parser.parse(&ss);
        widgetSs.append(ss);
    }
    styleSelector.styleSheets += widgetSs;
...
}

这堆东西看起来好繁琐啊,如果widget特别多会不会吃不消?呵呵,没什么问题了,Qt都进行了cache处理,只不过这儿为了清晰起见,没有贴出半点cache的代码。

stylesheet与parent

前面说了,当设置stylesheet时,样式表会传递到其子widget(这是前面代码setStyle_helper的第二个参数为true来进行的)。

但既然是传递,当然和父子关系有关了:

void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
{
...
   d->inheritStyle();
...
}

根据情况,设置新的样式,或者恢复原来的样式:

void QWidgetPrivate::inheritStyle()
{
...
    setStyle_helper(newStyle, true);
...
    setStyle_helper(origStyle, true);
...
}

当然,对一个含有子widget的widget设置样式表时,也会对各个child调用这个函数。

QCss::Parser

qss 的语法分析是由QCss::Parser完成的。而这个东西在Qt的另一个地方也被使用:当在QTextDocument/QTextEdit中使用html时,用来处理<style>标记的内容。

我对CSS不熟,对语法分析也不熟。暂时到此为止了。

QCss::StyleRule

x:hover,y:clicked>z:checked
{prop1:value1;prop2:value2;}

QVector<QCss::Selector>

x:hover,y:clickedz:checked

QVector<QCss::Declaration>

{prop1:value1;prop2:value2;}

QCss::Declaration

prop1:value1;

参考


分享到:
评论

相关推荐

    qt switchbutton源码+应用

    Qt SwitchButton是一个在Qt框架下实现的开关按钮...通过深入研究"qt switchbutton源码+应用",开发者不仅可以学习到Qt控件的定制,还能了解事件处理、信号与槽的机制,以及QSS的用法,这些是构建高质量Qt应用的基础。

    QT5版本的RizekQssEditor源码

    5. **源码学习价值** 分析`RizekQssEditor`的源码,开发者可以深入理解`QT5`如何与`QSS`交互,学习如何实现界面实时渲染,以及如何在`QT5`中构建自定义的GUI应用。这对于提升`QT5`开发技能,尤其是涉及界面设计的...

    QT vista style 源码

    通过这个源码,开发者可以学习如何在Qt应用中自定义样式,以实现特定的视觉效果。 首先,我们需要了解Qt的样式系统。Qt使用QSS(Qt StyleSheet)来控制界面的外观和布局,类似于HTML中的CSS。QSS允许开发者使用类似...

    Qt美化界面、美化组件、自定义组件源码

    总的来说,Qt美化界面和组件源码的学习,包括了理解QSS、自定义组件、信号与槽机制以及布局管理等多方面的内容。掌握这些技能,开发者可以创造出既美观又实用的Qt应用程序,提升用户的操作体验。对于想要深入Qt开发...

    GuiAutoScale_qt伸缩_qt比例尺_GuiAutoScale_伸缩比例尺_qt列表_源码.rar

    在Qt框架中,GuiAutoScale是一个重要的概念,它涉及到用户界面(UI)的自适应性,特别是当应用程序在不同分辨率或DPI(dots ...同时,通过源码学习,可以深入理解Qt自动缩放机制的工作原理,提升UI设计和开发的技能。

    Qt词典软件源代码

    通过阅读和分析这个【Qt词典软件源代码】,开发者不仅可以学习到Qt框架的基本用法,还能深入了解桌面应用开发中的数据处理、网络通信、UI设计等多个方面。对于想要深入Qt开发或词典软件制作的人来说,这是一个非常有...

    qt箭头按钮源码.zip

    - 通过阅读源码,我们可以学习到如何创建自定义图形元素、处理事件以及如何将自定义控件集成到Qt应用程序中的实践方法。 综上所述,"qt箭头按钮源码.zip"提供的源码可能涉及了Qt中自定义按钮的设计和实现,包括...

    qt温湿度上位机源码

    开发者通过熟练运用QT的相关类库和技术,实现了与温湿度监测设备的通信,实时显示环境数据,并可能具备数据存储和回溯功能,是学习QT开发和物联网应用的实用案例。通过深入研究这个源码,开发者可以了解到如何构建...

    Qt高仿网易云音乐界面源码

    这个源码是Qt开发者学习和研究界面设计、交互实现以及Qt库应用的一个良好实例。Qt是一个跨平台的C++图形用户界面应用程序开发框架,广泛应用于桌面、移动和嵌入式设备的开发。 在该源码中,我们可以学习到以下几个...

    Qt自定义控件十套demo源码-续III.zip

    通过这些自定义控件的源码学习,开发者不仅可以了解Qt图形视图模型和事件处理机制,还能掌握如何利用Qt的绘图API创建复杂的用户界面。同时,这些源码实例也提供了良好的学习材料,帮助初学者快速掌握Qt自定义控件的...

    一个基于Qt的电话呼叫软件

    在这款电话软件中,设计者可能使用了Qt Designer工具来可视化设计界面,并通过QSS(Qt StyleSheet)定制了界面风格,以达到吸引用户的效果。 2. **网络通信**:实现局域网内的电话呼叫功能,软件需要支持TCP/IP或者...

    Qt竖向tab标签页面源码

    在Qt编程中,通常我们使用的`QTabWidget`控件默认是横向展示标签页的,但有时为了界面设计的需求,可能需要将标签页改...同时,深入学习Qt的自定义控件和绘画机制,将有助于你开发出更多具有创新性和个性化的界面组件。

    用Qt编译模仿的360界面;用到qss来处理美化界面;VS2015+Qt5.6.3编译通过

    对于压缩包中的"Qt_360"文件,可能包含了源代码、资源文件以及编译后的可执行文件,供学习者参考和研究。 总之,通过Qt和QSS,我们可以实现富有吸引力和个性化的用户界面,同时保持代码的简洁性和可维护性。在VS...

    【源码】基于Qt的2048游戏/ Qt for Android

    【源码】基于Qt的2048游戏/ Qt for Android 本文将深入探讨如何使用Qt框架开发2048游戏,并将其移植到Android平台。Qt是一个强大的跨平台应用程序开发框架,支持C++语言,同时也提供了QML作为声明式用户界面设计的...

    QT专业医疗界面仪器设计

    4. **样式表和主题**:掌握QSS(Qt StyleSheet)的使用,类似于HTML的CSS,可以为Qt界面定制样式,实现界面的个性化和品牌一致性。 5. **对话框与提示**:理解QDialog和 QMessageBox的用法,它们用于创建弹出式...

    一款自定义QSS样式表工具, 适合QT编译, 只有源码

    QSS,全称为Qt StyleSheet,是QT框架中用于定制GUI界面样式的机制,类似于网页设计中的CSS。这款名为“QUI-Creator”的工具正是为了解决QT应用的界面美化问题,特别适合那些没有专门美工资源的小团队和个人开发者...

    qt自定义界面放大缩小关闭

    在Qt框架中,开发自定义用户界面是一项基本任务,它允许开发者根据项目需求创建独特的交互体验。本主题将深入探讨如何在Qt中实现界面的放大、缩小和关闭功能,这对于初学者...不断实践和学习,你的Qt之旅将会更加顺畅。

    基于QT的温度计源码.zip

    QT是Qt Company开发的一种跨平台的应用程序开发框架,广泛用于创建桌面、移动和嵌入式系统的用户...通过研究这个源码,开发者不仅可以学习到如何使用QT创建桌面应用,还能了解到如何实现一个实时数据展示的可视化工具。

    Qt12宫格程序主界面全部源码

    理解这个源码可以让你深入学习Qt的布局管理、事件处理、自定义控件以及资源管理等核心概念。通过分析和学习,你可以掌握如何在Qt中构建一个具有复杂界面布局的应用程序。同时,这个12宫格程序也是一个很好的实践案例...

    利用Qt写的连连看游戏

    QSS(Qt StyleSheet)是Qt提供的类似CSS的样式语言,可用于轻松定制控件的样式,使得换肤变得更加方便。 另外,用户添加自己喜欢的图片可能涉及到资源管理和图像处理。Qt的QImage和QPixmap类提供了读取、显示和操作...

Global site tag (gtag.js) - Google Analytics