QSS语法介绍

一、QSS简述

QSS是Qt Style Sheets的简称,也就是Qt样式表,是Qt提供的一种用来自定义控件外观的机制。QSS大量参考了CSS的内容,但功能比CSS弱很多,体现在选择器要少、属性也少很多,并且不是所有属性都可以用在Qt的所有控件上。

二、QSS语法

2.1 样式规则

QSS包含了一个样式规则,一个样式规则由一个选择器和声明组成,选择器指定哪些部件由规则影响,声明指定哪些属性应该在部件上进行设置。例如:

QPushButton { color: red }

上面的例子中QPushButton是选择器,{ color: red }是声明,该规则指定QPushButton及其子类(例如:MyPushButton)应使用红色作为前景色。
QPushButton表示选择器,指定了所有的QPushButton或者是QPushButton的子类会受到影响。
注意:凡是继承自QPushButton的子类也会受到影响,这是与CSS中不同的地方,因为CSS应用的都是一些标签,没有类的层次结构,更加没有子类的概念。

后面的{color:red}则是是一个属性值对(property: value)列表,包含在花括号中,以分号分隔。整个意思就是设置QPushButton类以及其子类的所有实例的前景色是红色。
如果MyButton继承自QPushButton,那么上面的规则也会应用到所有MyButton控件上,但是如果规则是如下的:

MyButton{ color: red; }

则只会对MyButton的实例应用红色的前景颜色,而对QPushButton的实例没有应用。
几个选择器可以指定相同的声明,使用逗号(,)来分隔选择器。例如:

QPushButton, QLineEdit, QComboBox { color: red }

相当于三个规则序列:

QPushButton { color: red }
QLineEdit { color: red }
QComboBox { color: red }

参见Qt助手:Qt Style Sheets Reference中List of Properties部分。

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

2.2 选择器类型

选择器作用
通配选择器:*匹配所有的控件。
类型选择器:QPushButton匹配所有QPushButton和其子类的实例。
属性选择器:QPushButton[flat=”false”]匹配所有flat属性是false的QPushButton实例,注意该属性可以是自定义的属性,不一定非要是类本身具有的属性。
类选择器: .QPushButton匹配所有QPushButton的实例,但是并不匹配其子类。这是与CSS中的类选择器不一样的地方,注意前面有一个点号。
ID选择器: #myButton匹配所有id为myButton的控件实例,这里的id实际上就是objectName指定的值。
后代选择器: QDialog QPushButton所有QDialog容器中包含的QPushButton,不管是直接的还是间接的。
子选择器: QDialog > QPushButton所有QDialog容器下面的QPushButton,其中要求QPushButton的直接父容器是QDialog。

另外,上面所有的这些选择器可以联合使用,并且支持一次设置多个选择器类型,用逗号隔开。例如:

  • #frameCut,#frameInterrupt,#frameJoin 表示所有这些id使用一个规则。
  • #mytable QPushButton 表示选择所有id为mytable的容器下面的QPushButton实例。

注意:QDockWidget内部存在一个子窗口,这个子窗口盖住了qdockWidget,所以实际上是要对这个子窗口应用样式表

QDockWidget>QWidget
{
    border:2px solid blue;
}

2.3 子控件(Sub-Controls)

设置某些较复杂的控件,需要访问其子控件,例如QComboBox的下拉按钮、QSpinBox的上下箭头。可以使用双冒号(::)设置,例如:

QComboBox::drop-down { image: url(dropdown.png) }

子控件定位总是相对于另一个参考元素,这个参考元素可能是小部件或其它子控件。例如:QComboBox的::drop-down放置,默认的放置在QComboBox区域的右上角。

width和height属性可用于控制子控件的大小,
注意:设置一个图片会隐式地设置子控件的大小。

相对定位(position : relative):
可以改变子控件相对初始位置的偏移量。例如:按下QComboBox下拉按钮时,我们可能更喜欢用内部箭头偏移量来产生一个被按下的效果。代码如下:

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

绝对定位(position : absolute):
允许子控件改变位置和的大小而不受参考元素限制。

参见Qt助手:Qt Style Sheets Reference中List of Sub-Controls部分。

2.4 伪选择器(Pseudo-States)

伪状态是部件状态的程序规则,出现在选择器后面,用冒号(:)关联。例如,鼠标划过按钮:

QPushButton:hover { color: white }

伪状态可以用感叹号(!)运算符表示否定。例如,当鼠标不划过QRadioButton:

QRadioButton:!hover { color: red }

伪状态可以连接使用,这种情况下,相当于隐含了一个逻辑与。例如,当鼠标滑过选中的QCheckBox:

QCheckBox:hover:checked { color: white }

否定的伪状态也可以连接使用,例如,当鼠标划过一个非按下时按钮:

QPushButton:hover:!pressed { color: blue; }

可以使用逗号操作来表示逻辑或:

QCheckBox:hover, QCheckBox:checked { color: white }

伪状态也可以与子控件组合,例如:

QComboBox::drop-down:hover { image: url(dropdown_bright.png) }

参见Qt助手:Qt Style Sheets Reference中List of Pseudo-States部分。

2.5 优先级

QSS样式中指定相同的属性存在优先级。

指定相同属性时,更具体的优先级更高,例如:

QPushButton#okButton { color: blue }
QPushButton { color: red }

QPushButton#okButton 被认为比 QPushButton 更具体,因为它通常是指单个对象,而不是一类的所有实例。所以 okButton 这个按钮文本颜色会设置为blue,而其它按钮文本仍然设置为red。

利用伪状态比不指定伪状态那些选择器更具体。因此,下面的样式指定一个QPushButton应该有鼠标悬停文本颜色为白色,否则文本颜色为红色。

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

当两个选择器有相同的特殊性(同样具体),则后一条规则优先(最后优先),例如:

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

QPushButton:enabled { color: red }优先级更高,所以按钮默认 enabled 的情况下,无论鼠标是否悬停在按钮上,文本颜色始终为红色。

交换两者先后,例如:

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

则鼠标悬停在按钮上文本颜色为白色,不悬停enabled时为红色。

当然,也可以使文本颜色为白色的规则更加具体:

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

实现与前一例子一样的效果。

注意,对于QSS的计算,所有的类型选择具有相同的特殊性。

当不同类型选择器一起使用时,例如:

QPushButton { color: red }
QAbstractButton { color: blue }

QPushButton 继承 QAbstractButton,所以 QPushButton 比 QAbstractButton 更具体,本应该按钮文本颜色为红色。但事实上,QPushButton 和 QAbstractButton具有相同的特殊性,需要遵照最后出现的规则优先,所以实际上按钮文本颜色为蓝色。如果需要设置QPushButtons为红色文字,需要重新排序规则。

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+LI          {}  /* a=0 b=0 c=3 -> specificity =   3 */
H1 + *[REL=up]    {}  /* a=0 b=1 c=1 -> specificity =  11 */
UL OL LI.color    {}  /* a=0 b=1 c=3 -> specificity =  13 */
LI.color.width    {}  /* a=0 b=2 c=1 -> specificity =  21 */
#okButton         {}  /* a=1 b=0 c=0 -> specificity = 100 */

2.6 级联效应

QSS可以在QApplication、父部件、子部件中设置。冲突发生时,不论冲突规则的特殊性,部件自身的样式表总优先于任何继承样式表。考虑下面的例子。首先,我们在QApplication中设置样式表:

qApp->setStyleSheet("QPushButton { color: white }");

然后,设置QPushButton的样式表:

myPushButton->setStyleSheet("color: blue");

QPushButton样式表强制QPushButton(以及任何子部件)显示蓝色文字,尽管应用程序范围内的样式表提供的规则更具体。

2.7 继承性

在经典的CSS中,当字体和颜色没有明确设置时,它就会自动从父继承。当使用QSS时,部件不会自动从父继承字体和颜色。例如,一个QGroupBox中包含QPushButton:

qApp->setStyleSheet("QGroupBox { color: red; } ");

QPushButton不会继承其父QGroupBox的颜色,而是显示系统的颜色。

三、常用样式

3.1 文字属性

示例说明
color:#999999;文字颜色
font-family:Microsoft Yahei,sans-serif;字体家族
font-size:16pt;字体大小
font-style:itelic;(normal、oblique)字体样式
letter-spacing:1pt;字间距离
line-height:200%;设置行高
font-weight:bold;(lighter、normal、数值900)字体粗细
text-decoration:underline;(line-through、overline、none)字体修饰
text-align:left;(right、center、justify)文字左对齐
vertical-align:top;(bottom、middle、text-top、text-bottom)垂直对齐方式
text-transform:uppercase;(lowercase、capitalize)英文大写
font-variant: small-caps;(normal)小型大写字母

3.2 背景样式:

示例说明
background:black;背景颜色为黑色
background-color:#F5E2EC;背景颜色
background-image:url(/image/bg.gif);背景图片
background:transparent;透视背景
background-repeat : repeat;重复排列-网页默认
background-position : center;指定背景位置-居中对齐

3.3 边框空白

示例说明
padding:5px 10px 5px 10px;所有边框留空白
padding-top:10px;上边框留空白
padding-right:10px;右边框留空白
padding-bottom:10px;下边框留空白
padding-left:10px;左边框留空白

3.4 框线

建议书写方式说明
border:1px solid red;所有边框线
border-top:1px solid #6699cc;上框线
border-bottom:1px solid #6699cc;下框线
border-left:1px solid #6699cc;左框线
border-right:1px solid #6699cc;右框线
border-radius:8px;边框圆角半径

以上是建议书写方式,但也可以使用常规书写方式,如下表所示:

常规书写方式说明
border-top-color:#369;设置上框线颜色
border-top-width:1px;设置上框线宽度
border-top-style:solid设置上框线样式

其他框线样式如下:

  • solid - 实线
  • dotted - 虚线
  • double - 双线
  • inset - 凹框
  • outset - 凸框
  • groove - 立体内凸框
  • ridge - 立体浮雕框

3.5 边界样式

边界样式及示例说明
margin-top:10px;上边界值
margin-right:10px;右边界值
margin-bottom:10px;下边界值
margin-left:10px;左边界值

注:px:相对长度单位,像素(Pixel)。pt:绝对长度单位,点(Point)。

四、遇到的问题

4.1 在QWidget中设定了setObjectName,就是不起作用。

解决方法:重写paintEvent。

#ifndef BROWSEWIDGET_H
#define BROWSEWIDGET_H

#include <QObject>
#include <QWidget>
#include <QLabel>

class BrowseWidget : public QWidget
{
    Q_OBJECT
public:
    explicit BrowseWidget(QWidget *parent = nullptr);
signals:

protected:
    void paintEvent(QPaintEvent *event);
public slots:

private:
    void initUI();
};

#endif // BROWSEWIDGET_H
#include "browsewidget.h"
#include<QVBoxLayout>
#include<QHBoxLayout>
#include <QStylePainter>
#include <QStyleOption>
BrowseWidget::BrowseWidget(QWidget *parent) : QWidget(parent)
{
    initUI();
    this->setObjectName("BrowseWidget");
}

void BrowseWidget::paintEvent(QPaintEvent *event)
{
    QStylePainter painter(this);
    QStyleOption opt;
    opt.initFrom(this);
    opt.rect=rect();
    painter.drawPrimitive(QStyle::PE_Widget, opt);
    QWidget::paintEvent(event);
}

void BrowseWidget::initUI()
{
    QVBoxLayout *mainVLayout=new QVBoxLayout(this);
    QLabel *lbl=new QLabel("切片浏览");
    mainVLayout->addWidget(lbl);
    setLayout(mainVLayout);
}

4.2 使用.qss文件来指定app样式时,.qss修改了编译app后发现没起效,就算重编译.qrc(资源文件)也不行,只有重编译整个app才行。

解决方法: .qrc(资源文件)会在编译时声称qrc_xxx.cpp,需要将qrc_xxx.cpp加入编译,才能真正起效。另外,翻译文件.ts等不起效原因也可能是如此。

4.3 在visual studio中qss默认是文本模式,可以将其默认打开方式设置成CSS,就可以方便地编辑qss了。

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值