Qt QSS(一)之基础篇_qss环境-程序员宅基地

技术标签: QSS  css  Qt  

QSS详解

简述

QSS(Qt Style Sheets)是Qt样式表,与制作前端web中使用CSS来美化网页一样, QSS为Qt提供属性、伪状态、子控件等机制来自定义控件外观。对于设计Qt应用程序,QSS是必须掌握的,因为它能让你付出最少的代价,美化应用程序。而不用去继承QWidget,做很多复杂的工作(当然我们不是说这种方式不重要,后面会介绍这种方式,并且以实现ribbon为目标)。另外,QtQuick和QGraphicsView能够定制更好的用户体验,后面再一点点体验和分享给大家。

QSS 编辑器

工欲善其事,必先利其器,一款好的编辑器有利于快速编写所需样式。

  1. Qt Creator
    Qt Creator默认是不会高亮qss内容,这个只需要配置一下:

    • 进入:工具 -> 选项 -> 环境 -> MIME 类型。
    • 在【已注册的MIME类型】处输入“text/css”可以快速定位,然后在【详情】中的“模式”处添加 *.qss,即将原来的“模式”改为:*.css;*.CSSL;*.qss
      【注意】中间用分号(;)分隔
  2. QSS Editor
    QSS Editor可以预览,没有语法提示。

  3. Rizek Qss Editor

  4. Kineticwing IDE
    KiWi 是一款智能、轻便、便携的 IDE,可以更快捷、更轻松的进行 WEB 开发。支持 HTML、CSS、QSS、SASS、JavaScript、PHP、XML、ASP、Perl 等。
    对 QSS 的支持,主要包含以下功能:

  • 代码突出显示(语法着色)

  • 括号高亮显示(当光标位于包含字符的开始和结束之间时,编辑器会成对突出显示大括号)

  • 折叠代码段

  • 保存状态标记(绿色是保存状态,红色是未保存状态)

  • 智能自动完成
    缺点:无法实时预览。

QSS 语法

QSS 包含了一个样式规则序列,术语和语法规则几乎和CSS相同。

样式规则

  1. QSS包含了一个样式规则序列,一个样式规则由一个选择器和声明组成,选择器指定哪些部件由规则影响,声明指定哪些属性应该在部件上进行设置。例如:
    QPushButton { color: red }
    上面的例子中QPushButton是选择器,{ color: red }是声明,该规则指定QPushButton及其子类(例如:MyPushButton)应使用红色作为前景色。

  2. QSS通常不区分大小写(即:color、Color、COLOR、cOloR指同一属性),唯一例外就是类名(class names)、对象名(object names)、属性名(property names)区分大小写。

  3. 几个选择器可以指定相同的声明,使用逗号(,)来分隔选择器。例如:
    QPushButton, QLineEdit, QComboBox { color: red }
    等价于

    QPushButton { color: red }
    QLineEdit { color: red }
    QComboBox { color: red }
    
  4. 声明部分的规则是一个属性值对(property: value)列表,包含在花括号中,以分号分隔。例如:
    QPushButton { color: red; background-color: white }
    更多声明规则,可以查阅Qt文档,Qt Style Sheets Reference中List of Properties部分,
    或是直接查阅在线文档Qt Style Sheets Reference

  5. 选择器类型

选择器 例子 详细描述
通用选择器 * 匹配所有控件
类型选择器 QPushButton 匹配QPushButton实例和其子类
属性选择器 QPushButton[flat="false"] 匹配QPushButton中flat属性为false的实例。可以用此选择器来测试任何支持QVariant::toString()的属性,此外,支持特殊的类属性、类名称。此选择器也可以用来测试动态属性(参考助手:Qt Style Sheets Examples中Customizing Using Dynamic Properties部分)。还可以使用~=替换=,测试QStringList类型的属性是否包含给定的QString。 警告:如果Qt属性值在设置样式之后更改,那么可能需要强制重新计算样式。实现的一个方法是取消样式,然后重新设置一遍。
类选择器 .QPushButton 匹配QPushButton实例,但是不包括其其子类。其等价于 *[class~="QPushButton"]
ID选择器 QPushButton#okButton 匹配所有对象名为“okButton”的QPushButton实例
后代选择器 QDialog QPushButton 匹配所有属于QDialog后代(子部件,孙子部件…)的QPushButton实例
子选择器 QDialog > QPushButton 匹配所有属于QDialog直接子部件的QPushButton实例
  1. 子控件
  • 对于样式复杂的控件,需要访问其子控件,例如QComboBox的下拉按钮,或QSpinBox递增邪恶向上箭头和递减的向下箭头。选择器应该包含子控件,让他可以限制指定控件的副控件的应用规则。例如:
    QComboBox::drop-down { image: url(dropdown.png) }
    上述规则指定了QComboBoxe下拉按钮样式,虽然双冒号(::)语法让人想起CSS3伪元素,但Qt子控件从概念上讲有不同的级联语义
  • 子控件定位总是相对于另一个参考元素。这个参考元素可能是小部件或其它子控件。例如:QComboBox的::drop-down放置,默认的放置在QComboBox区域的右上角,::drop-down放置,默认的在::drop-down子控件的中央,参考助手:Qt Style Sheets Reference中List of Stylable Widgets部分。
    可以使用subcontrol-origin改变子控件原始的默认位置,
QComboBox {
    margin-right: 20px;
}
QComboBox::drop-down {
    subcontrol-origin: margin;
}

下拉框在边框内的对齐方式,可以通过subcontrol-position属性改变。
高度和宽度属性可以控制子控件的尺寸,
注意】设置图片的大小会隐式的改变子控件的大小,这个比较重要,你试着用32px的icon作为控件的图标,工作在1920x1080的屏幕上。 当换成4k屏(4096×2160)时,你的所有控件都变小,缩成一堆。解决方案(根据像素换成大图标,没有去实践,手上没有4K屏)…这个问题找到准确解决方案在补上。

相对位置方案 (position : relative), 即允许子控件相对于其初始位置做偏置。例如: QComboBox下拉按钮被按下时,我们可以使其内部的下拉箭头在做一些偏置,达到被按下的效果。具体实现如下:

QComboBox::down-arrow {
    image: url(down_arrow.png);
}
QComboBox::down-arrow:pressed {
    position: relative;
    top: 1px; left: 1px;
}

绝对位置方案 (position : absolute),允许相对于参考元素改变子控件位置和大小。
一旦位置被设定,这些子控件将被和普通部件(widgets)视为相同,并且可以使用盒模型样式(参考助手:Customizing Qt Widgets Using Style Sheets中The Box Model部分)。
**注意:**对于复杂的部件,如:QComboBox和QScrollBar,如果一个属性或子控件被定制,所有其它属性或子控件必须被定制好。

  1. 伪状态(Pseudo-States)
    什么是伪状态,比如:当鼠标经过或停留在按钮时,按钮颜色发生改变。
  • 选择器可以包含伪状态,表示基于控件的状态限制应用程序的规则。伪状态出现在选择器后面,用冒号(:)关联。例如下面的应用规则,鼠标划过按钮:
    QPushButton:hover { color: white }

  • 伪状态可以用取反声明符(!)表示否定,例如下面的应用规则,鼠标没有经过QRadioButton上方:
    QRadioButton:!hover { color: red }

  • 伪状态可以连接使用,用冒号(:)将所有伪状态连起来,相当于逻辑与(AND)操作符。例如:鼠标经过一个被选中的按钮。
    QCheckBox:hover:checked { color: white }

  • 伪状态链中可以有取反(!)的伪状态,例如:鼠标经过一个没有被按下的按钮
    QPushButton:hover:!pressed { color: blue; }

  • 如果需要,逻辑或(OR)可以被表示成逗号(,)
    QCheckBox:hover, QCheckBox:checked { color: white }

  • 伪状态可以用在子控件中,例如:
    QComboBox::drop-down:hover { image: url(dropdown_bright.png) }

更加详细可以参考助手:Qt Style Sheets Reference中List of Pseudo-States部分。

  1. 消除冲突
  • 几种风格规则用不同值来指定相同属性会引起冲突,考虑下面的样式规则:
QPushButton#okButton { color: gray }
QPushButton { color: red }

两个规则都匹配到对象名为okButtonQPushButton实例,那么color这个属性有冲突,所以必须考虑两个选择器的特殊性。对象名为okButtonQPushButton实例是比QPushButton特殊,因为他通常指的一个对象,而不是所有QPushButton对象。

  • 同样的,有伪状态选择器则比没有指定伪状态的选择器特殊,因此,下面的例子中, 当鼠标经过QPushButton时,使用的应该时白色的文本
QPushButton:hover { color: white }
QPushButton { color: red }
  • 当然也有更加棘手的情况,如果特殊性相同,那最后声明的选择器优先。
    如下:QPushButton 文本颜色为红色
QPushButton:hover { color: white }
QPushButton:enabled { color: red }

如果要设置QPushButton 文本颜色为白色,只需要将上面白色的属性样式放到最后,如下所示:

QPushButton:enabled { color: red }
QPushButton:hover { color: white }

或者使QPushButton 前景为白色属性的样式更加特殊,如下所示

#添加了enabled的伪状态
QPushButton:hover:enabled { color: white } 
QPushButton:enabled { color: red }
  • 类似的问题出现在类型选择器,如下所示,两个类型选择器为继承关系:
QPushButton { color: red }
QAbstractButton { color: gray }

上面的两条样式规则都会作用于QPushButton(自从QPushButton继承 QAbstractButton), 那这里就有颜色属性的争执。 因为QPushButton继承 QAbstractButton,则认为QPushButtonQAbstractButton更加具有特殊性。
当然,对于样式的计算,所有拥有相同特殊性的类型的选择器,则顺序在最后的样式优先。或者说,所有QAbstractButtons的前景颜色都设置为灰色,包括QPushButtons。如果我们真正想 QPushButtons设置为红色的前景,我们可以把描述样式的规则重新排序。

  1. 样式规则特殊性小结
    为了确定一个规则的特殊性,QSS遵循CSS2规范:
  • 选择器ID属性的数量 (=a)
  • 选择器其他属性和伪状态类性数量 (=b)
  • 选择器元素名的数量 (=c)
  • 忽略伪元素 (例如:子控件)
    把a-b-c连接在一起(一个拥有很大基数的数字系统)决定特殊性。
    如下一些例子:
*             {}  /* a=0 b=0 c=0 -> specificity =   0 */
LI            {}  /* a=0 b=0 c=1 -> specificity =   1 */
UL LI         {}  /* a=0 b=0 c=2 -> specificity =   2 */
UL OL+LIa      {}  /* a=0 b=0 c=3 -> specificity =   3 */
H1 + *[REL=up]{}  /* a=0 b=1 c=1 -> specificity =  11 */
UL OL LI.red  {}  /* a=0 b=1 c=3 -> specificity =  13 */
LI.red.level  {}  /* a=0 b=2 c=1 -> specificity =  21 */
#x34y         {}  /* a=1 b=0 c=0 -> specificity = 100 */
  1. 级联
    样式可以说被设置在 QApplication, 在父控件,子控件。任意控件的有效样式可以通过合并其祖先的(父级,祖父级等)以及 QApplication上设置的样式获得。
    考虑这样的一个结果,自动设置一个控件样式规则,它的优先级高于其祖先或者 QApplication 的样式规则规则。 如下,为 QApplication设置样式表
    qApp->setStyleSheet("QPushButton { color: white }");
    然后我们为QPushButton对象设置样式,如下所示:
    myPushButton->setStyleSheet("* { color: blue }");
    QPushButton的样式就会迫使QPushButton(以及它的子控件)前景文本为蓝色。尽管应用程序范围内提供了更多特殊的规则,但QPushButton(以及它的子控件)并不会使用。
    如果按照下面这种方式写,其结果是相同的:
    myPushButton->setStyleSheet("color: blue");
    除非 QPushButton有子控件,那么这个样式将不会影响到。不过一般QPushButton不会有子控件。
    样式极联是一个复杂的主题。请参考CSS2 Specification,请注意,目前Qt没有实现。

  2. 继承
    在经典的CSS中,当字体和颜色等项目没有显式设置,它会自动继承父级控件的样式。默认情况下,在QSS中,一个控件是不会自动继承它父级控件的字体和颜色的设置。
    例如: QGroupBox 里面的子控件QPushButton:
    qApp->setStyleSheet("QGroupBox { color: red; } ");
    QPushButton没有显式设置颜色, 因此,QPushButton设置为系统的颜色,而没有继承它的父级控件颜色。如果我们想设置QGroupBox及其子级控件的样式,我们可以这么写:
    qApp->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");
    于此相比,可以使用 QWidget::setFont()QWidget::setPalette() 设置字体和调色板用到子控件中。
    如果你想字体和调色板可以传播到子控件,可以设置这个标志: Qt::AA_UseStyleSheetPropagationInWidgetStyles
    使用方法:
    QCoreApplication::setAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles, true);
    当控件风格中字体和调色板的传播使能,字体和调色板通过QSS所做的更改将会执行,即使用户手动调用对应 QWidget::setPalette()QWidget::setFont() 的方法在所有QWidgets 所针对的样式目标。

  3. 控件在NameSpace中
    类型选择器可以被用于特定的控件风格。例如:

class MyPushButton : public QPushButton {
    // ...
}

// ...
qApp->setStyleSheet("MyPushButton { background: yellow; }");

Qt 样式使用控件的类名(QObject::className())来决定是否应用类型选择器。当自定义的控件在命名空间中(namespaces), 类名(QObject::className())返回<namespace>::<classname>。这个命名方式于子控件的样式规则命名方式有冲突。为了克服这个问题,当空间选择器在命名空间内时,我们使用“–”替代“::”。如下所示:

namespace ns {
    class MyPushButton : public QPushButton {
        // ...
    }
}

// ...
qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");

子控件的样式规则,如果命名空间的表示方式不做更改,那就会发生冲突:

QComboBox::down-arrow {
    image: url(down_arrow.png);
}
  1. 设置QObject的属性
    在Qt4.3以后,任何可以设计为Q_PROPERTY 都可以使用 qproperty-<property name>的语法。如下例子:
    MyLabel { qproperty-pixmap: url(pixmap.png); }
    MyGroupBox { qproperty-titleColor: rgb(100, 200, 100); }
    QPushButton { qproperty-iconSize: 20px 20px; }
    

如果属性参考 Q_ENUMS的枚举声明,我们应该参考它常量的名字,而不是数值。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u014202280/article/details/106608003

智能推荐

class和struct的区别-程序员宅基地

文章浏览阅读101次。4.class可以有⽆参的构造函数,struct不可以,必须是有参的构造函数,⽽且在有参的构造函数必须初始。2.Struct适⽤于作为经常使⽤的⼀些数据组合成的新类型,表示诸如点、矩形等主要⽤来存储数据的轻量。1.Class⽐较适合⼤的和复杂的数据,表现抽象和多级别的对象层次时。2.class允许继承、被继承,struct不允许,只能继承接⼝。3.Struct有性能优势,Class有⾯向对象的扩展优势。3.class可以初始化变量,struct不可以。1.class是引⽤类型,struct是值类型。

android使用json后闪退,应用闪退问题:从json信息的解析开始就会闪退-程序员宅基地

文章浏览阅读586次。想实现的功能是点击顶部按钮之后按关键字进行搜索,已经可以从服务器收到反馈的json信息,但从json信息的解析开始就会闪退,加载listview也不知道行不行public abstract class loadlistview{public ListView plv;public String js;public int listlength;public int listvisit;public..._rton转json为什么会闪退

如何使用wordnet词典,得到英文句子的同义句_get_synonyms wordnet-程序员宅基地

文章浏览阅读219次。如何使用wordnet词典,得到英文句子的同义句_get_synonyms wordnet

系统项目报表导出功能开发_积木报表 多线程-程序员宅基地

文章浏览阅读521次。系统项目报表导出 导出任务队列表 + 定时扫描 + 多线程_积木报表 多线程

ajax 如何从服务器上获取数据?_ajax 获取http数据-程序员宅基地

文章浏览阅读1.1k次,点赞9次,收藏9次。使用AJAX技术的好处之一是它能够提供更好的用户体验,因为它允许在不重新加载整个页面的情况下更新网页的某一部分。另外,AJAX还使得开发人员能够创建更复杂、更动态的Web应用程序,因为它们可以在后台与服务器进行通信,而不需要打断用户的浏览体验。在Web开发中,AJAX(Asynchronous JavaScript and XML)是一种常用的技术,用于在不重新加载整个页面的情况下,从服务器获取数据并更新网页的某一部分。使用AJAX,你可以创建异步请求,从而提供更快的响应和更好的用户体验。_ajax 获取http数据

Linux图形终端与字符终端-程序员宅基地

文章浏览阅读2.8k次。登录退出、修改密码、关机重启_字符终端

随便推点

Python与Arduino绘制超声波雷达扫描_超声波扫描建模 python库-程序员宅基地

文章浏览阅读3.8k次,点赞3次,收藏51次。前段时间看到一位发烧友制作的超声波雷达扫描神器,用到了Arduino和Processing,可惜啊,我不会Processing更看不懂人家的程序,咋办呢?嘿嘿,所以我就换了个思路解决,因为我会一点Python啊,那就动手吧!在做这个案例之前先要搞明白一个问题:怎么将Arduino通过超声波检测到的距离反馈到Python端?这个嘛,我首先想到了串行通信接口。没错!就是串口。只要Arduino将数据发送给COM口,然后Python能从COM口读取到这个数据就可以啦!我先写了一个测试程序试了一下,OK!搞定_超声波扫描建模 python库

凯撒加密方法介绍及实例说明-程序员宅基地

文章浏览阅读4.2k次。端—端加密指信息由发送端自动加密,并且由TCP/IP进行数据包封装,然后作为不可阅读和不可识别的数据穿过互联网,当这些信息到达目的地,将被自动重组、解密,而成为可读的数据。不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。2.使用时,加密者查找明文字母表中需要加密的消息中的每一个字母所在位置,并且写下密文字母表中对应的字母。_凯撒加密

工控协议--cip--协议解析基本记录_cip协议embedded_service_error-程序员宅基地

文章浏览阅读5.7k次。CIP报文解析常用到的几个字段:普通类型服务类型:[0x00], CIP对象:[0x02 Message Router], ioi segments:[XX]PCCC(带cmd和func)服务类型:[0x00], CIP对象:[0x02 Message Router], cmd:[0x101], fnc:[0x101]..._cip协议embedded_service_error

如何在vs2019及以后版本(如vs2022)上添加 添加ActiveX控件中的MFC类_vs添加mfc库-程序员宅基地

文章浏览阅读2.4k次,点赞9次,收藏13次。有时候我们在MFC项目开发过程中,需要用到一些微软已经提供的功能,如VC++使用EXCEL功能,这时候我们就能直接通过VS2019到如EXCEL.EXE方式,生成对应的OLE头文件,然后直接使用功能,那么,我们上篇文章中介绍了vs2017及以前的版本如何来添加。但由于微软某些方面考虑,这种方式已被放弃。从上图中可以看出,这一功能,在从vs2017版本15.9开始,后续版本已经删除了此功能。那么我们如果仍需要此功能,我们如何在新版本中添加呢。_vs添加mfc库

frame_size (1536) was not respected for a non-last frame_frame_size (1024) was not respected for a non-last-程序员宅基地

文章浏览阅读785次。用ac3编码,执行编码函数时报错入如下:[ac3 @ 0x7fed7800f200] frame_size (1536) was not respected for anon-last frame (avcodec_encode_audio2)用ac3编码时每次送入编码器的音频采样数应该是1536个采样,不然就会报上述错误。这个数字并非刻意固定,而是跟ac3内部的编码算法原理相关。全网找不到,国内音视频之路还有很长的路,音视频人一起加油吧~......_frame_size (1024) was not respected for a non-last frame

Android移动应用开发入门_在安卓移动应用开发中要在活动类文件中声迷你一个复选框变量-程序员宅基地

文章浏览阅读230次,点赞2次,收藏2次。创建Android应用程序一个项目里面可以有很多模块,而每一个模块就对应了一个应用程序。项目结构介绍_在安卓移动应用开发中要在活动类文件中声迷你一个复选框变量

推荐文章

热门文章

相关标签