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

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 stylesheet

    Qt stylesheet 感觉还不错。I think this is a good resoure for qt stylesheet new leaner.

    Qt StyleSheet 样式表实例

    这是一个大神总结的一些Qt界面美化的实例 每一种方式大神都有实例代码, 可以好好借鉴一下 希望大家共同进步

    Qt5-stylesheet-样式表

    配合本人博客Qt开发总结(29)——样式表的例子,内含三个典型的样式表,几乎涵盖了Qt样式表的所有语法规则。具体内容可以移步到我的个人博客下学习。

    Qt5stylesheet

    Qt5环境下实现style和stylesheet换窗口背景色和控件背景色,功能强大!

    qt黑色styleSheet样式表

    QT界面开发 样式挑战

    Qt利用StyleSheet更改大部分默认控件外观

    Qt4.8.4,利用StyleSheet更改大部分默认控件外观,对于个性化界面比较有帮助

    Qt蓝色styleSheet样式表

    qt界面开发

    QT自定义精美换肤界面(主题资源CSS暗黑风格)源码可用

    QT自定义精美换肤界面,主题资源CSS(暗黑风格)源码亲测可用 引用简单: QFile file(QString("./css/%1.css").arg("stylesheet")); file.open(QFile::ReadOnly); QString qss = QLatin1String(file.readAll()); ...

    Qt tableview 和qchart的初步使用范例

    自定义tablemodel 使用qchart绘制曲线图,横轴使用时间轴 使用stylesheet优化界面显示 http://blog.csdn.net/liang19890820/article/details/50557240 修改自 一去丶二三里 整理的代码framelesshelper

    QtStyleSheetDemo.rar

    QT样式表setStyleSheet使用例程,包含13种不同的样式,实现简单换皮肤效果。 (关注可不用积分下载) 查看效果:https://blog.csdn.net/long00000kid/article/details/114982478

    StyleSheet

    StyleSheet、StyleSheet

    QT Spinbox

    通过重写虚函数实现功能的调换, 例子是Qspinbox

    stylesheet

    style,样式表设计。。。。。。。。。。。。。。。。

    Qt QWidget 设置样式表不生效的两种解决方案

    使用Qt Designer 设计界面,但在Qt Designer里设置好样式表,使用快捷键 shift + alt + r 进行预览,样式都是正常的,但程序运行起来,样式就不生效了。两种解决方法: 详情可以到文章里看一下。 ...

    史上最强QT自定义界面纯QSS

    找遍百度谷歌,潜心钻研官方QSS应用示例http://qt-project.org/doc/qt-4.8/stylesheet-examples.html,陆续完善三个月,终于得出一套自定义UI的QSS方案,只需要查找替换对应七个颜色值,就可制作出一套精美皮肤!

    Qt Style Sheet.doc

    QT样式QSS使用说明,QT styleSheet的使用方法,SS教程非常少,贡献一篇给大家。

    Qt Creator的主题修改文件

    下载后保存任意路径,并修改Qt Creator的快捷方式的目标路径为D:\Qt\Qt5.3.1\Tools\QtCreator\bin\qtcreator.exe -stylesheet D:\Qt\Qt5.3.1\Tools\QtCreator\bin\stylesheet.css 具体使用方法详见博客.

    qt实现toolbox

    实现了qt对qtoolbox的美化,按钮的stylesheet的修改,界面美化

    QT 学习笔记

    qt widget全屏显示 获取屏幕分辨率 QGraphicsView添加背景图片 设置无边框(标题栏)的应用程序 QLineEdit输入按IP地址校验 定时器,点击按钮 光标位置编辑 QTableWidgte 圆角控件 用stylesheet方式 圆角窗口

Global site tag (gtag.js) - Google Analytics