一.背景介绍
在网页前端开发领域中,CSS是⼀个⾄关重要的部分.描述了⼀个网页的"样式".从而起到对⽹⻚美化的作用.
所谓样式,包括不限于大小,位置,颜色,背景,间距,字体等等.
Qt仿照 CSS 的模式,引⼊了QSS,来对Qt中的控件做出样式上的设定,从而允许程序猿写出界⾯更好看的代码.
当然,由于Qt本身的设计理念和网页前端还是存在⼀定差异的,因此QSS中只能⽀持部分 CSS 属性.整体来说QSS要⽐CSS更简单⼀些.
二.基本语法
选择器 {
属性名:属性值
}
• 选择器描述了"哪个widget要应⽤样式规则".
• 属性则是⼀个键值对,属性名表⽰要设置哪种样式,属性值表⽰了设置的样式的值.
代码示例:
创建一个按钮
修改代码
ui->pushButton->setStyleSheet("QPushButton {color: blue;background:silver}");
运行结果:
注:此时我们仅针对第一个按钮设置样式,此时新建按钮不受影响
三.设置方式
1.指定控件样式设置
QWidget 中包含了setStyleSheet ⽅法,可以直接设置样式.(如上面eg所示)
另⼀方面,给指定控件设置样式之后,该控件的子元素也会受到影响.
eg:子元素受到影响
创建一个按钮
对widget设置样式
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//对widget进行设置
this->setStyleSheet("QWidget{color:blue;}");
}
运行结果:
观察到样式对于子控件按钮同样会⽣效.
QPushButton是QWidget的子类
2.全局样式设置
还可以通过QApplication 的 setStyleSheet ⽅法设置整个程序的全局样式.
全局样式优点:
• 使同⼀个样式针对多个控件⽣效,代码更简洁.
• 所有控件样式内聚在⼀起,便于维护和问题排查.
eg1:使用全局样式
创建多个按钮+使用水平布局管理器管理按钮
修改main函数
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setStyleSheet("QPushButton{color:blue}");
MainWindow w;
w.show();
return a.exec();
}
运行结果:
eg2:样式的层叠特性
如果通过全局样式给某个控件设置了属性1,通过指定控件样式给控件设置属性2,那么这两个属性都会产生作用。(在两个属性不冲突的前提下)
创建两个按钮+垂直布局管理器管理
修改MainWindow.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setStyleSheet("QPushButton{color:blue}");
MainWindow w;
w.show();
return a.exec();
}
修改widget.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->pushButton->setStyleSheet("font-size:80px");
}
运行结果:
形如上述这种属性叠加的效果,我们称为"层叠性".
CSS全称为Cascading Style Sheets,其中Cascading就是"层叠性"的意思.QSS也继承了这样的设定
eg3:样式的优先级特性
创建两个按钮
修改MainWindow.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//将全局按钮文字设置为红色
a.setStyleSheet("QPushButton{color:red}");
MainWindow w;
w.show();
return a.exec();
}
修改widget.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 将第一个按钮颜色设置为蓝色
ui->pushButton->setStyleSheet("QPushButton{color:blue}");
}
运行结果:
观察可知,第一个颜色已经改为蓝色。
在CSS中也存在类似的优先级规则.通常来说都是"局部"优先级高于"全局"优先级.
相当于全局样式先"奠定基调",再通过指定控件样式来"特事特办".
关于QSS层叠特性与优先级特性的总结:
若全局与局部设置不冲突,则效果叠加;
若全局与局部设置发生冲突,局部优先级高于全局。
3.从文件加载样式表
上述代码都是把样式通过硬编码的⽅式设置的.这样使 QSS 代码和 C++ 代码耦合在⼀起了,并不方便代码的维护.因此更好的做法是把样式放到单独的文件中,然后通过读取⽂件的方式来加载样式.
代码示例:从⽂件加载全局样式
1)在界⾯上创建两个按钮
2)创建resource.qrc ⽂件,并设定前缀为/
3)创建myQss.qss 文件,修改内容
4)将自定义的myQss.qss文件引入到qrc文件中
5)修改main.cpp,新增⼀个函数⽤来加载样式
QString loadQSS() {
QFile file(":/myQss.qss");
// 打开⽂件
file.open(QFile::ReadOnly);
// 读取⽂件内容. 虽然 readAll 返回的是 QByteArray, 但是 QString 提供了
//QByteArray 版本的构造函数.
QString style = file.readAll();
// 关闭⽂件
file.close();
return style;
}
6)修改main.cpp,在main函数中调⽤上述函数,并设置样式
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 调⽤上述函数加载样式
const QString& style = loadQSS();
a.setStyleSheet(style);
MainWindow w;
w.show();
return a.exec();
}
运行结果:
4.使用Qt Designer 编辑样式
QSS 也可以通过 Qt Designer 直接编辑,从⽽起到实时预览的效果.同时也能避免C++和QSS代码的耦合。
eg:使用 Qt Designer 编辑样式
1)在界⾯上创建⼀个按钮
2)右键按钮,选择"改变样式表"
3)在弹出的样式表编辑器中,可以直接填写样式.填写完毕,点击 OK 即可.
4)此时Qt Designer的预览界⾯就会实时显⽰出样式的变化.
运行程序:
当我们发现⼀个控件的样式不符合预期的时候,要记得排查这四个地⽅:
• 全局样式
• 指定控件样式
• qss⽂件中的样式
• ui⽂件中的样式
四.选择器
1.选择器分类
eg:使⽤id选择器
1)在界⾯上创建3个按钮, objectName 为 pushButton , pushButton_2 , pushButton_3
2)修改main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 设置全局样式
QString style = "";
style += "QPushButton { color: yellow; background-color:silver }";
style += "#pushButton { color: red; }";
style += "#pushButton_2 { color: green; }";
a.setStyleSheet(style);
MainWindow w;
w.show();
return a.exec();
}
运行结果:
当某个控件⾝上,通过类型选择器和 ID 选择器设置了冲突的样式时,ID选择器样式优先级更 ⾼.
同理,如果是其他的多种选择器作⽤同⼀个控件时出现冲突的样式,也会涉及到优先级问题. Qt⽂档上有具体的优先级规则介绍(参The Style Sheet Syntax的Conflict Resolution章节).
实践中我们可以简单的认为,选择器描述的范围越精准,则优先级越高。⼀般来说,ID 选择器优 先级是最⾼的
2.子控件选择器
有些控件内部包含了多个"⼦控件".比如QComboBox 的下拉后的⾯板,比如QSpinBox的上下按钮 等.可以通过⼦控件选择器:: ,针对上述子控件进行样式设置.
eg1:
创建下拉框
在阿里巴巴矢量库中下载图片,保存在qrc文件中
修改main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString style="";
style+="QComboBox::down-arrow{image:url(:/down.png)}";
a.setStyleSheet(style);
MainWindow w;
w.show();
return a.exec();
}
运行结果:
eg2:修改进度条的颜色
1)在界⾯上创建⼀个进度条.
2)在Qt Designer 右侧的属性编辑器中,找到QWidget的styleSheet 属性.
编辑如下内容:
• 其中的chunk 是选中进度条中的每个"块".使用QProgressBar::text 则可以选中⽂本.
运行结果:
3.伪类属性
3.1概念
伪类选择器,是根据控件所处的某个状态被选择的.
例如按钮被按下,输⼊框获取到焦点,⿏标移动到某个控件上等.
• 当状态具备时,控件被选中,样式⽣效.
• 当状态不具备时,控件不被选中,样式失效.
使用:的⽅式定义伪类选择器.
3.2 常用伪类选择器
3.3 代码示例
设置按钮的伪类样式.
1)在界⾯上创建⼀个按钮
2)修改main.cpp文件
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString style="";
style+="QPushButton{background-color:red}";
style+="QPushButton:hover{background-color:yellow}";
style+="QPushButton:pressed{background-color:blue}";
//设置全局样式
a.setStyleSheet(style);
MainWindow w;
w.show();
return a.exec();
}
运行结果:
默认时
鼠标放置在按钮上时
鼠标点击时
使用事件也能实现一样效果
五.样式属性
1.概念
QSS中的样式属性⾮常多,不需要都记住.核⼼原则还是⽤到了就去查.⼤部分的属性和CSS是⾮常相似的.
(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
(2)颜色
17种标准色:aqua, black, blue, fuchsia, gray, green, lime, maroon, navy,olive, orange, purple, red, silver, teal, white, yellow
(3)内边距
padding: 4px; /* 文字边距 */
padding-left: 5px; /* 文字左边距 */
padding-right: 10px; /* 文字右边距 */
padding-top: 3px; /* 文字顶边距 */
padding-bottom: 3px; /* 文字底边距 */
(4)外边距
margin: 14px 18px 20px 18px; /*外边距 顺序上右下左 */
margin-top: 14px;
margin-right: 18px;
margin-bottom: 20px;
margin-left: 18px;
(5) 背景
background-color: #202122; /* 背景颜色 */
background-color: qlineargradient(); /* 背景颜色:线性渐变*/
background-color: qradialgradient(); /* 背景颜色:辐射渐变*/
background-color: qconicalgradient(); /* 背景颜色:梯形渐变*/
background-image:url(boder.png); /* 背景图片 */
background-position: ; /* 背景图片对齐方式 */
background-repeat: ; /* 背景图片平铺方式 */
(6)边框
border-style: dotted;(点线) dashed;(虚线) solid; double;(双线) groove;(槽线) ridge;(脊状) inset;(凹陷) outset;
border-width:; 边框宽度
border-color:#;
简写方法border:width style color; /*简写*/
border: 1px solid #FDBC03; /* 边框:宽度 颜色*/
border-image:url(boder.png) 4 8 12 16; /* 边界图 切线 */
border-radius: 4px; /* 角弧度 */
border-top-left-radius: ; /* 角弧度:左上角*/
border-top-right-radius: ; /* 角弧度:右上角*/
border-bottom-left-radius: ; /* 角弧度:左下角*/
border-bottom-right-radius: ; /* 角弧度:右下角*/
2.盒子模型
在QSS盒子模型中,一个控件被看作一个矩形的盒子,它由以下几个组成部分构成
内容(Content):盒子中实际包含的内容,如文本、图像等。
内边距(Padding):内容与边框之间的空白区域,用于控制内容与边框之间的间距。
边框(Border):围绕内容和内边距的线条,用于定义控件的边界。
外边距(Margin):盒子与相邻控件之间的空白区域,用于控制盒子与其他控件之间的间距。
这些组成部分构成了一个完整的盒子,它们的大小、样式和颜色都可以通过QSS样式表进行控制。
在QSS中,我们可以使用一些属性来控制盒子模型的各个部分:
width和height属性:用于设置控件的宽度和高度。
padding属性:用于设置内边距的大小,可以通过分别设置上、右、下、左四个方向的内边距。
border属性:用于设置边框的样式、宽度和颜色。
margin属性:用于设置外边距的大小,可以通过分别设置上、右、下、左四个方向的外边距。
这些属性可以通过在QSS样式表中为控件选择器设置相应的属性值来控制盒子模型。