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

智能推荐

机器学习入门案例:鸢尾花数据集分类 绘制PR曲线-程序员宅基地

文章浏览阅读3.1k次,点赞2次,收藏35次。案例使用鸢尾花数据集进行分类预测,并绘制评价分类性能的PR曲线图认识分类任务和数据集Iris(鸢尾花)数据集案例演示中使用的是有监督的机器学习算法:SVM 支持向量机建立模型的流程如..._训练集向量测试集鸢尾花数据集案例

python callable错误_python错误:TypeError: 'module' object is not callable 解决方法-程序员宅基地

文章浏览阅读3.9k次。python错误:TypeError: 'module' object is not callable 解决方法发布于 2014-12-08 16:49:36 | 16689 次阅读 | 评论: 1 | 来源: PHPERZPython编程语言Python 是一种面向对象、解释型计算机程序设计语言,由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年。Python..._typeerror: 'yolo' object is not callable

统计的回归分析 --matlab实现_matlab nlintool-程序员宅基地

文章浏览阅读2.1w次,点赞46次,收藏339次。前面我们讲过曲线拟合问题。曲线拟合问题的特点是,根据得到的若干有关变量的 一组数据,寻找因变量与(一个或几个)自变量之间的一个函数,使这个函数对那组数 据拟合得好。通常,函数的形式可以由经验、先验知识或对数据的直观观察决定,要 作的工作是由数据用小二乘法计算函数中的待定系数。从计算的角度看,问题似乎已 经完全解决了,还有进一步研究的必要吗?目录1 数据表的基础知识1.1 样本空间..._matlab nlintool

美国贝勒大学计算机科学专业怎么样,贝勒大学专业排名一览(含历年专业排名信息,USNEWS美国大学排名版)...-程序员宅基地

文章浏览阅读213次。贝勒大学优势专业介绍教育学院、商学院、医学院、法学院贝勒大学历年专业排名爱荷华大学政治学专业在2018年USNEWS美国大学排名中排名第37爱荷华大学英语学专业在2018年USNEWS美国大学排名中排名第42爱荷华大学学生辅导及个人服务专业在2018年USNEWS美国大学排名中排名第10爱荷华大学心理学专业在2018年USNEWS美国大学排名中排名第25爱荷华大学物理专业在2018年USNEWS美..._贝勒大学专业排名

微信小程序实现日历功能、日历转换插件、calendar_微信小程序日历-程序员宅基地

文章浏览阅读2.5k次,点赞4次,收藏10次。微信小程序实现日历功能、日历转换插件、calendar_微信小程序日历

Java集合容器面试题(2020最新版)_1.8为什么只采用两次扰动-程序员宅基地

文章浏览阅读1k次,点赞2次,收藏7次。Java集合容器面试题(2020最新版)最近看到这篇文章作者写的很不错,总结的到位希望更多的人看到,能够帮到更多的人。原创作者 ThinkWon原文链接:https://thinkwon.blog.csdn.net/article/details/104588551) 序号内容链接地址1..._1.8为什么只采用两次扰动

随便推点

sqlserver修改实例名_sqlserver修改实例名称-程序员宅基地

文章浏览阅读9.1k次。虚拟机测试复制的的时候发现,复制的虚拟机实例还是开始创建的服务器名字;那sqlserver复制就不能继续进行了,所以就要修改:一个实例名一个服务器名;SELECT @@SERVERNAME select serverproperty('servername')下面 sqlif serverproperty('servername') begin declare _sqlserver修改实例名称

Mac adb devices时,一直显示emulator-5554 offline如何解决_mac emulator-5554 offline-程序员宅基地

文章浏览阅读3.5k次,点赞2次,收藏2次。问题:在终端执行adb devices时,一直显示emulator-5554 offline,adb disconnect也删除不掉。原因:有程序占用5555端口,导致adb认为5554不能作为第一个设备启用办法:lsof -i:5555,查询占用端口对应的PID值, command + space中搜索“活动监视器”,找到PID一栏,根据1中的PID值删除对应进程 再次在..._mac emulator-5554 offline

Delphi XE10,Json 生成和解析,再利用indyhttp控件Post_delphixe json post-程序员宅基地

文章浏览阅读1.9k次。--不多说,直接上代码procedure TFrmMain.Brand;varJSONObject, jsonparam: TJSONObject; // JSON类jsonArray: TJSONArray; // JSON数组变量i: Integer;Flag_Do: Boolean;jsonToSend: TStringStream;jsonStr,..._delphixe json post

一个简单的基于MVC模式的登录验证过程_mvc的网站登录验证应用: 建立几个jsp页面,在这里我们主要做登录,所以我们要建logi-程序员宅基地

文章浏览阅读5.1k次,点赞2次,收藏10次。MVC即Model-View-Controller(模型-视图-控制器)是一种软件设计模式,MVC最早出现在Smalltalk语言中,后来在Java中得到广泛应用。简述_mvc的网站登录验证应用: 建立几个jsp页面,在这里我们主要做登录,所以我们要建logi

vagrant安装centos7_vagant中安装centos7-程序员宅基地

文章浏览阅读5.8k次,点赞4次,收藏13次。流程如下:1. 下载安装vitural-box2. 下载vagrant3. 添加box4. 初始化box,初始化系统,启动系统1.下载安装virtural-box地址:https://www.virtualbox.org/如上图示,找到对应的版本下载,我用的是window系统,就下载window。至于安装,没什么好说,选好安装路劲,一直点下一步就行。2.下载安装vagr..._vagant中安装centos7

C++ static、const和static const 以及它们的初始化_c++ static 常量 初始化-程序员宅基地

文章浏览阅读5.9w次,点赞22次,收藏144次。 const定义的常量在超出其作用域之后其空间会被释放,而static定义的静态常量在函数执行后不会释放其存储空间。 static表示的是静态的。类的静态成员函数、静态成员变量是和类相关的,而不是和类的具体对象相关的。即使没有具体对象,也能调用类的静态成员函数和成员变量。一般类的静态函数几乎就是一个全局函数,只不过它的作用域限于包含它的文件中。 在C++中,static静态成员变量不能在类的内部初始化。在类的内部只是声明,定义必须在类定义体的_c++ static 常量 初始化

推荐文章

热门文章

相关标签