Qt - QSS样式表

1. QSS简介

Qt样式表(style sheet)是用于定制用户界面的强有力的机制,其概念、术语是收到HTML中的级联样式表(Cascading Style Sheets,CCS)启发而来,只是Qt样式表是用用于窗体界面的

与HTML的CSS类似,Qt的样式表是纯文本的格式定义,在应用程序运行时可以载入和解析这些样式定义。使用样式表可以定义各种界面组件(QWidget类及其子类)的样式,从而使应用程序的界面呈现不同的效果。很多软件具有换肤功能,使用Qt的样式表就可以很容易的实现这样的功能

多多翻看Qt官方文档,所有控件都有案例:在索引栏输入Qt style

CSS样式表学习:http://www.w3school.com.cn/css/css_syntax.asp

1.1 盒子模型

CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。

盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。

下面的图片说明了盒子模型(Box Model):

 

不同部分的说明:

  • Margin(外边距) - 清除边框外的区域,外边距是透明的。

  • Border(边框) - 围绕在内边距和内容外的边框。

  • Padding(内边距) - 清除内容周围的区域,内边距是透明的。

  • Content(内容) - 盒子的内容,显示文本和图像。

为了正确设置元素在所有浏览器中的宽度和高度,你需要知道的盒模型是如何工作的。

 

2. QSS加载方式

方式一:在代码中加载

myDialog->setStyleSheet("QLineEdit { background-color: yellow }");
nameEdit->setStyleSheet("background-color: yellow");

 

方式二:读文件的方式加载

QFile file("://qss/styles.css");
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
    qWarning("styles.css open falied");
}
this->setStyleSheet(file.readAll());

 

方式三:对整个软件的所有控件样式进行设置

#include "mainwindow.h"

#include <QApplication>
#include <QDebug>
#include <QFile>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow w;
    w.show();
    
    QFile qss("StyleSheet.qss");
    if(!qss.open(QFile::ReadOnly))
    {
        qWarning("StyleSheet.css open falied");
    }
    app.setStyleSheet(qss.readAll());
    qss.close();
    
    return app.exec();
}

或者,本质都是一样的

#include "mainwindow.h"

#include <QApplication>
#include <QFile>
#include "global_function.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    
    MainWindow w;
    w.show();
    qApp->setStyleSheet(g_GetStrStyle());

    return a.exec();
}

 通过加载StyleSheet.css文件,对整个软件的所有控件样式进行设置。这种方式“一劳永逸”,可以设计自己的风格,所有软件重复使用。

 

3. QSS样式表用法

1.全局使用

qApp->setStyleSheet(“QLineEdit { background-color: yellow }”);

2.子类及子类以下使用

myDialog->setStyleSheet(“QLineEdit { background-color: yellow }”);

3.某一个特定的控件

使用QObject::setObjectName()设定一个ID

通过id选择器

myDialog->setStyleSheet(“QLineEdit#nameEdit { background-color: yellow }”);

4.直接在控件上使用

nameEdit->setStyleSheet(“background-color: yellow”);

 

4. QSS选择器类型

4.1 通配选择器

 *  

  匹配所有的控件

4.2 类型选择器

QPushButton 

  匹配所有QPushButton和其子类的实例

QPushButton {background: gray;}

4.3 属性选择器

QPushButton[flat="false"]

   匹配所有flat属性是false的QPushButton实例,注意该属性可以是自定义的属性,不一定非要是类本身具有的属性

QPushButton[STYLE_KEY='dangerous'] { background: magenta; }
/*openButton->setProperty("STYLE_KEY",  "dangerous");*/

4.4 类选择器

.QPushButton 

 匹配所有QPushButton的实例,但是并不匹配其子类。这是与CSS中的类选择器不一样的地方,注意前面有一个点号

.RedButton { background: magenta; }
 
/*
openButton->setProperty("class",  "RedButton");
closeButton->setProperty("class", "RedButton");
*/

4.5 ID选择器

#myButton

 匹配所有id为myButton的控件实例,这里的id实际上就是objectName指定的值

#openButton, #closeButton { background: magenta; }

4.6 后代选择器

QDialog QPushButton

   所有QDialog容器中包含的QPushButton,不管是直接的还是间接的

QDialog {background: gray;}
/* 设置 QDialog中的 QPushButton 的 QSS */
QDialog QPushButton 
{
    border: 2px solid magenta;
    border-radius: 10px;
    background: white;
    padding: 2px 15px;
}

4.7 子选择器

QFrame> QPushButton

   所有QFrame容器下面的QPushButton,其中要求QPushButton的直接父容器是QFrame,注意和后代选择器的区别

QFrame {background: gray;}
QFrame > QPushButton 
{
    border: 2px solid magenta;
    border-radius: 10px;
    background: white;
    padding: 2px 15px;
}

4.8 伪类选择器

选择器:状态 作为选择器,支持 ! 操作符,表示 非。

QPushButton:hover { color: white }
QCheckBox:checked { color: white }
QCheckBox:!checked { color: red }


所有的这些选择器可以联合使用,并且支持一次设置多个选择器类型,用逗号隔开,这点与CSS一样,例如:

#frameCut,#frameInterrupt,#frameJoin 表示所有这些id使用一个规则。

#mytable  QPushButton 表示选择所有id为mytable的容器下面的QPushButton实例

 

5. QSS常用属性

5.1 字体

大小 {font-size: x-large;}(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX、PD

样式 {font-style: oblique;}(偏斜体) italic;(斜体) normal;(正常)

行高 {line-height: normal;}(正常) 单位:PX、PD、EM

粗细 {font-weight: bold;}(粗体) lighter;(细体) normal;(正常)

变体 {font-variant: small-caps;}(小型大写字母) normal;(正常)

大小写 {text-transform: capitalize;}(首字母大写) uppercase;(大写) lowercase;(小写) none;(无)

修饰 {text-decoration: underline;}(下划线) overline;(上划线) line-through;(删除线) blink;(闪烁)

字体名:

微软雅黑:Microsoft YaHei  宋体:SimSun  黑体:SimHei  仿宋: FangSong  楷体:  KaiTi

隶书:LiSu  幼圆:YouYuan  华文细黑:STXihei  华文楷体:STKaiti  华文宋体:STSong

华文中宋:STZhongsong  华文仿宋:STFangsong  方正舒体:FZShuTi  方正姚体:FZYaoti  华文彩云:STCaiyun

华文琥珀:STHupo  华文隶书:STLiti  华文行楷:STXingkai  华文新魏:STXinwei

font: 15px "Segoe UI";             /* 字体:大小 名称 */  
 
font-family: "Segoe UI";           /* 字体名称 */  

5.2 颜色

17种标准色:aqua, black, blue, fuchsia, gray, green, lime, maroon, navy,olive, orange, purple, red, silver, teal, white, yellow

color: rgb(255,255,255);   
color: #F5F5F5;               /* 前景(文本)颜色 */  
 
color: qlineargradient();     /* 前景(文本)颜色:线性渐变*/  
 
color: qradialgradient();     /* 前景(文本)颜色:辐射渐变*/  
 
color: qconicalgradient();    /* 前景(文本)颜色:梯形渐变*/

5.3 内边距

padding: 14px 18px 20px 18px;              /*内边距 顺序上右下左 */
 
padding-left: 5px;                 /* 文字左边距 */  
 
padding-right: 10px;               /* 文字右边距 */  
 
padding-top: 3px;                  /* 文字顶边距 */  
 
padding-bottom: 3px;               /* 文字底边距 */

5.4 外边距

margin: 14px 18px 20px 18px; /*外边距 顺序上右下左 */
 
margin-top: 14px;
 
margin-right: 18px;
 
margin-bottom: 20px;
 
margin-left: 18px;

5.5 背景

background-color: #202122;              
background-color: rgb(113,240,255);       /* 背景颜色 */
 
background-color: qlineargradient();    /* 背景颜色:线性渐变*/  
 
background-color: qradialgradient();    /* 背景颜色:辐射渐变*/  
 
background-color: qconicalgradient();   /* 背景颜色:梯形渐变*/  
 
background-image:url(boder.png);        /* 背景图片 */  
 
background-position: ;                 /* 背景图片对齐方式 */  
 
background-repeat: ;                   /* 背景图片平铺方式 */

5.6 边框

border-style: solid;/*边框类型*/
/*===============================*/
dotted - 定义点线边框
dashed - 定义虚线边框
solid - 定义实线边框
double - 定义双边框
groove - 定义 3D 坡口边框。效果取决于 border-color 值
ridge - 定义 3D 脊线边框。效果取决于 border-color 值
inset - 定义 3D inset 边框。效果取决于 border-color 值
outset - 定义 3D outset 边框。效果取决于 border-color 值
none - 定义无边框
hidden - 定义隐藏边框
/*===============================*/

border-width: 2px;                     /*边框宽度*/

border-color: #FDBC03;                 /*边框颜色*/

border: 1px solid #FDBC03;             /* 边框:宽度 类型 颜色*/  
 
border-image:url(boder.png) 4 8 12 16; /* 边界图 切线 */  
 
border-radius: 4px;                    /* 角弧度 */  
 
border-top-left-radius: 4px;           /* 角弧度:左上角*/  
 
border-top-right-radius: 4px;          /* 角弧度:右上角*/  
 
border-bottom-left-radius: 4px;      /* 角弧度:左下角*/  
 
border-bottom-right-radius: 4px;     /* 角弧度:右下角*/

5.7 宽高

width:12px;           /*设置宽度*/
 
height:40px;          /*设置高度*/
 
min-width:65px;       /*最小宽度*/
 
min-height:12px;      /*最小高度*/
 
max-width:12px;       /*最大宽度*/
 
max-height:12px;      /*最大高度*/

 

6. QSS伪状态与子控件

6.1 伪状态列表

:checked                        /*button部件被选中*/ 
:unchecked                      /*button部件未被选中*/ 
:disabled                       /*部件被禁用*/ 
:enabled                        /*部件被启用*/ 
:focus                          /*部件获得焦点*/ 
:hover                          /*鼠标位于部件上*/ 
:indeterminate                  /*checkbox或radiobutton被部分选中*/ 
:off                            /*部件可以切换,且处于off状态*/ 
:on                             /*部件可以切换,且处于on状态*/ 
:pressed                        /*部件被鼠标按下*/


6.2 子部件列表

::down-arrow        /*combo box或spin box的下拉箭头*/ 
::drop-down         /*combo box的下拉箭头*/ 
 
::indicator              /*checkbox、radio button或可选择group box的指示器*/ 
::item               /*menu、menu bar或status bar的子项目*/ 
::menu-indicator          /*push button的菜单指示器*/ 
::title              /*group box的标题*/ 
 
::down-button         /*spin box的向下按钮*/
::up-arrow           /*spin box的向上箭头*/ 
::up-button          /*spin box的向上按钮*/

 

7. QSS级联

QT样式表可以设置在应用程序、父组件、子组件上。通过合并组件的祖先(父亲、祖父等)可以获取任意组件的有效样式表,以及设置在应用程序上的任何样式表。

冲突发生时,不论冲突规则的特性如何,组件自己的样式表总是优先于任何继承而来的样式表。同样,父组件的样式表优先于祖父组件的样式表。

这样的结果是,在一个组件上设置样式规则会自动获得比祖先组件的样式表或是应用程序的样式表指定的其他规则更高的优先级。例如,首先在应用程序设置样式表

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

然后,在QPushButton对象设置一个样式表

myPushButton->setStyleSheet("* { color: blue }");

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

下列写法也会得到相同的结果:

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

但如果QPushButton有子组件,样式表不会对子组件有效果。

样式表级联是一个复杂的主题,更详细的内容请参考CSS2规范。QT目前没有实现。

 

8. QSS继承

在经典的CSS中,当元素的字体和颜色没有显示设置时,会自动从父组件继承。使用QT样式表时,一个组件不会自动继承父组件设置的字体和颜色。例如,一个QGroupBox包含一个QPushButton:

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

QPushButton并没有显示设置颜色,因此并不是继承父组件QGroupBox的颜色,而是拥有系统的颜色。如果要设置QGroupBox及其子组件的颜色,如下:

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

相比之下,使用QWidget::setFont() 和 QWidget::setPalette()为子组件设置字体和画板。

 

9. QT官方示例

官方示例链接:http://doc.qt.io/archives/qt-4.8/stylesheet-examples.html

Qt样式表示例

现在我们将看到一些例子来开始使用Qt样式表。

样式表用法

自定义前景和背景颜色

让我们从将黄色设置为应用程序中所有QLinEdits的背景色开始。这可以像这样实现:

qApp->setStyleSheet("QLineEdit { background-color: yellow }");

如果我们希望属性只应用于QLineEdit,它是特定对话框的子(或孙子或孙子),我们宁愿这样做

myDialog->setStyleSheet("QLineEdit { background-color: yellow }");

如果我们希望属性只应用于一个特定的QLineEdit,我们可以使用QObject:setObjectName()给它一个名字,并使用IDl选择器来引用它:

myDialog->setStyleSheet("QLineEdit#nameEdit { background-color: yellow }");

或者,我们可以直接在QLineEdit上设置background-color属性,省略选择器:

nameEdit->setStyleSheet("background-color: yellow");

为了确保良好的对比度,我们还应该为文本指定合适的颜色:

nameEdit->setStyleSheet("color: blue; background-color: yellow");

这可能是一个好主意,改变所选文本的颜色:

nameEdit->setStyleSheet("color: blue;"
                        "background-color: yellow;"
                        "selection-color: yellow;"
                        "selection-background-color: blue;");

使用动态属性自定义

在很多情况下,我们需要呈现具有强制字段的表单。为了向用户表明该字段是强制性的,一个有效的(尽管在美学上是可疑的)解决方案是使用黄色作为这些字段的背景色。事实证明,这是非常容易实现使用Qt样式表。首先,我们将使用以下应用程序范围的样式表:

*[mandatoryField="true"] { background-color: yellow }

这意味着每个强制性字段Qt属性设置为true的小部件将具有黄色背景。

然后,对于每个强制字段小部件,我们只需动态地创建一个强制性字段属性并将其设置为true。例如:

QLineEdit *nameEdit = new QLineEdit(this);
nameEdit->setProperty("mandatoryField", true);

QLineEdit *emailEdit = new QLineEdit(this);
emailEdit->setProperty("mandatoryField", true);

QSpinBox *ageSpinBox = new QSpinBox(this);
ageSpinBox->setProperty("mandatoryField", true);

使用Box模型自定义QPushButton

这一次,我们将展示如何创建一个红色的QPushButton。这个QPushButton可能会连接到一个非常具有破坏性的代码片段。

首先,我们很想使用这个样式表:

QPushButton#evilButton { background-color: red }

 然而,结果是一个无聊的,没有边框的扁平按钮:

事情是这样的:

  • >我们提出了一个仅仅使用原生样式无法满足的要求(例如,Windows XP主题引擎不允许我们指定按钮的背景色)。
  • >因此,按钮是使用样式表呈现的。
  • >我们没有为border-width和border-style指定任何值,所以默认情况下我们获得一个样式为none的o像素宽边框。

让我们通过指定边框来改善这种情况:

QPushButton#evilButton {
    background-color: red;
    border-style: outset;
    border-width: 2px;
    border-color: beige;
}

事情看起来已经好多了。但是按钮看起来有点挤。让我们使用padding在边框和文本之间指定一些间距。此外,我们将强制执行最小宽度,圆角,并指定一个更大的字体,使按钮看起来更好:

QPushButton#evilButton {
    background-color: red;
    border-style: outset;
    border-width: 2px;
    border-radius: 10px;
    border-color: beige;
    font: bold 14px;
    min-width: 10em;
    padding: 6px;
}

剩下的唯一问题是,当我们按下按钮时,它没有反应。我们可以通过指定一个稍微不同的背景来解决这个问题颜色和使用不同的边框样式。

QPushButton#evilButton {
    background-color: red;
    border-style: outset;
    border-width: 2px;
    border-radius: 10px;
    border-color: beige;
    font: bold 14px;
    min-width: 10em;
    padding: 6px;
}
QPushButton#evilButton:pressed {
    background-color: rgb(224, 0, 0);
    border-style: inset;
}

自定义QPushButton的菜单指示子控件

子控件允许访问小部件的子元素。例如,与菜单关联的QPushButton(使用QPushButton:setMenu())有一个菜单指示器。我们来定制一下红色按钮的菜单指示器:

QPushButton#evilButton::menu-indicator {
    image: url(myindicator.png);
}

默认情况下,菜单指示器位于填充矩形的右下角。我们可以通过指定subcontrol-position和subcontrol-origin来改变这一点,以不同的方式锚定指示器。我们也可以使用top和left来移动指示器几个像素。例如:

QPushButton::menu-indicator {
    image: url(myindicator.png);
    subcontrol-position: right center;
    subcontrol-origin: padding;
    left: -2px;
}

这将myindicator.png定位到QPushButton填充矩形的中右位置(参见subcontrol-origin了解更多信息)。

 

复杂选择器示例

由于红色似乎是我们最喜欢的颜色,让我们通过设置以下应用程序范围的样式表将QLineEdit中的文本设置为红色:

QLineEdit { color: red }

然而,我们想给一个视觉指示,一个QLineEdit是只读的,使其显示为灰色:

QLineEdit { color: red }
QLineEdit[readOnly="true"] { color: gray }

在某些时候,我们的设计团队要求注册表单(对象名称为registrationDialog)中的所有qlineedit都是棕色的:

QLineEdit { color: red }
QLineEdit[readOnly="true"] { color: gray }
#registrationDialog QLineEdit { color: brown }

在几次Ul设计会议之后,我们决定所有的qdialog都应该是棕色的qlineedit。

QLineEdit { color: red }
QLineEdit[readOnly="true"] { color: gray }
QDialog QLineEdit { color: brown }

测试:如果我们在QDialog中有一个只读的QLineEdit会发生什么?[提示:上面的冲突解决部分解释了在这种情况下会发生什么。]

 

 

posted @ 2022-07-17 08:40  [BORUTO]  阅读(2374)  评论(0)    收藏  举报