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

智能推荐

18个顶级人工智能平台-程序员宅基地

文章浏览阅读1w次,点赞2次,收藏27次。来源:机器人小妹  很多时候企业拥有重复,乏味且困难的工作流程,这些流程往往会减慢生产速度并增加运营成本。为了降低生产成本,企业别无选择,只能自动化某些功能以降低生产成本。  通过数字化..._人工智能平台

electron热加载_electron-reloader-程序员宅基地

文章浏览阅读2.2k次。热加载能够在每次保存修改的代码后自动刷新 electron 应用界面,而不必每次去手动操作重新运行,这极大的提升了开发效率。安装 electron 热加载插件热加载虽然很方便,但是不是每个 electron 项目必须的,所以想要舒服的开发 electron 就只能给 electron 项目单独的安装热加载插件[electron-reloader]:// 在项目的根目录下安装 electron-reloader,国内建议使用 cnpm 代替 npmnpm install electron-relo._electron-reloader

android 11.0 去掉recovery模式UI页面的选项_android recovery 删除 部分菜单-程序员宅基地

文章浏览阅读942次。在11.0 进行定制化开发,会根据需要去掉recovery模式的一些选项 就是在device.cpp去掉一些选项就可以了。_android recovery 删除 部分菜单

mnn linux编译_mnn 编译linux-程序员宅基地

文章浏览阅读3.7k次。https://www.yuque.com/mnn/cn/cvrt_linux_mac基础依赖这些依赖是无关编译选项的基础编译依赖• cmake(3.10 以上)• protobuf (3.0 以上)• 指protobuf库以及protobuf编译器。版本号使用 protoc --version 打印出来。• 在某些Linux发行版上这两个包是分开发布的,需要手动安装• Ubuntu需要分别安装 libprotobuf-dev 以及 protobuf-compiler 两个包•..._mnn 编译linux

利用CSS3制作淡入淡出动画效果_css3入场效果淡入淡出-程序员宅基地

文章浏览阅读1.8k次。CSS3新增动画属性“@-webkit-keyframes”,从字面就可以看出其含义——关键帧,这与Flash中的含义一致。利用CSS3制作动画效果其原理与Flash一样,我们需要定义关键帧处的状态效果,由CSS3来驱动产生动画效果。下面讲解一下如何利用CSS3制作淡入淡出的动画效果。具体实例可参考刚进入本站时的淡入效果。1. 定义动画,名称为fadeIn@-webkit-keyf_css3入场效果淡入淡出

计算机软件又必须包括什么,计算机系统应包括硬件和软件两个子系统,硬件和软件又必须依次分别包括______?...-程序员宅基地

文章浏览阅读2.8k次。计算机系统应包括硬件和软件两个子系统,硬件和软件又必须依次分别包括中央处理器和系统软件。按人的要求接收和存储信息,自动进行数据处理和计算,并输出结果信息的机器系统。计算机是脑力的延伸和扩充,是近代科学的重大成就之一。计算机系统由硬件(子)系统和软件(子)系统组成。前者是借助电、磁、光、机械等原理构成的各种物理部件的有机组合,是系统赖以工作的实体。后者是各种程序和文件,用于指挥全系统按指定的要求进行..._计算机系统包括硬件系统和软件系统 软件又必须包括

随便推点

进程调度(一)——FIFO算法_进程调度fifo算法代码-程序员宅基地

文章浏览阅读7.9k次,点赞3次,收藏22次。一 定义这是最早出现的置换算法。该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。该算法实现简单,只需把一个进程已调入内存的页面,按先后次序链接成一个队列,并设置一个指针,称为替换指针,使它总是指向最老的页面。但该算法与进程实际运行的规律不相适应,因为在进程中,有些页面经常被访问,比如,含有全局变量、常用函数、例程等的页面,FIFO 算法并不能保证这些页面不被淘汰。这里,我_进程调度fifo算法代码

mysql rownum写法_mysql应用之类似oracle rownum写法-程序员宅基地

文章浏览阅读133次。rownum是oracle才有的写法,rownum在oracle中可以用于取第一条数据,或者批量写数据时限定批量写的数量等mysql取第一条数据写法SELECT * FROM t order by id LIMIT 1;oracle取第一条数据写法SELECT * FROM t where rownum =1 order by id;ok,上面是mysql和oracle取第一条数据的写法对比,不过..._mysql 替换@rownum的写法

eclipse安装教程_ecjelm-程序员宅基地

文章浏览阅读790次,点赞3次,收藏4次。官网下载下载链接:http://www.eclipse.org/downloads/点击Download下载完成后双击运行我选择第2个,看自己需要(我选择企业级应用,如果只是单纯学习java选第一个就行)进入下一步后选择jre和安装路径修改jvm/jre的时候也可以选择本地的(点后面的文件夹进去),但是我们没有11版本的,所以还是用他的吧选择接受安装中安装过程中如果有其他界面弹出就点accept就行..._ecjelm

Linux常用网络命令_ifconfig 删除vlan-程序员宅基地

文章浏览阅读245次。原文链接:https://linux.cn/article-7801-1.htmlifconfigping &lt;IP地址&gt;:发送ICMP echo消息到某个主机traceroute &lt;IP地址&gt;:用于跟踪IP包的路由路由:netstat -r: 打印路由表route add :添加静态路由路径routed:控制动态路由的BSD守护程序。运行RIP路由协议gat..._ifconfig 删除vlan

redux_redux redis-程序员宅基地

文章浏览阅读224次。reduxredux里要求把数据都放在公共的存储区域叫store里面,组件中尽量少放数据,假如绿色的组件要给很多灰色的组件传值,绿色的组件只需要改变store里面对应的数据就行了,接着灰色的组件会自动感知到store里的数据发生了改变,store只要有变化,灰色的组件就会自动从store里重新取数据,这样绿色组件的数据就很方便的传到其它灰色组件里了。redux就是把公用的数据放在公共的区域去存..._redux redis

linux 解压zip大文件(解决乱码问题)_linux 7za解压中文乱码-程序员宅基地

文章浏览阅读2.2k次,点赞3次,收藏6次。unzip版本不支持4G以上的压缩包所以要使用p7zip:Linux一个高压缩率软件wget http://sourceforge.net/projects/p7zip/files/p7zip/9.20.1/p7zip_9.20.1_src_all.tar.bz2tar jxvf p7zip_9.20.1_src_all.tar.bz2cd p7zip_9.20.1make && make install 如果安装失败,看一下报错是不是因为没有下载gcc 和 gcc ++(p7_linux 7za解压中文乱码