文章目录
Qt样式表
Qt样式表
(Qt Style Sheet)是用于定制用户界面的一种机制。
是受到到HTML中的**层级样式表CSS
**(Cascading Style Sheets,CS2S)启发而来,只是Qt样式表是用于窗体界面的。
我们可以使用QSS来完成对软件的换肤功能。
我们首先了解一下QSS包括CSS最基本的结构:盒子模型
盒子模型是qss技术所使用的一种思维模型。盒子模型是指将界面设计页面中的内容元素看作一个个装了东西的矩形盒子。
每个矩形盒子包括:
- 内容(content)
- 内边距(padding)
- 边框(border)
- 外边距(margin)。
我们可以设置这些不同的参数来完成对他们的调节。
如何编写样式表?
我们选择一个最基本的Label作为演示:
然后**右键
这个Label,选择改变样式表
**
我们就可以在这个窗口中愉快的编写样式表了。
font
简单示例:
- font-family:字体族
- color:字体颜色
- font-size:字体尺寸
- font-weight:字体的宽度样式
- font-style:字体样式(斜体还是正常)
等同于直接设置 font:font-style font-weight font-size font- faily
中间用空格隔开。
效果如下:
border
-
border-style:设置边框的样式
-
border-color:设置边框颜色
-
border-width:设置边框的宽度。
同理可以使用: border: border-width border-style border-color
padding
设置文本居中对齐,注意QSS没有text-align,因此必须设置内边距padding。
在这里我们设置了 padding-left:30px,得到如下的效果,同时也可以直接:
- padding:上右下左
- padding-right ,top,bottom
有关更加详细的层叠样式表的知识请看CSS或QSS文档。
如何高效的编写QSS?
我们注意到在qtcreator上写QSS没有提示,而且字体很小,很丑,我们可以通过以下的方式来在vscode上编写,然后导入到qt项目中,众所周知vscode上具有对CSS语法的提示与高亮功能。
步骤:
- 首先vscode上新建一个**
CSS文件
** ,然后保存到qt的项目中,注意就添加一个图片一样,添加一个 **qrc
**文件,然后导入到qrc中。
- 导入到qrc之后,选择拷贝链接,然后转到
widget.cpp
文件中,输入以下的代码:
代表我们创建了一个QFile文件,然后这个文件指向这个样式表,然后我们打开它,直接**readAll
**读取全部内容即可。
//外部加载
QFile qssFile(":/images/qss/qt.css");
if (qssFile.open(QFile::OpenModeFlag::ReadOnly)){
this->setStyleSheet(qssFile.readAll());
}
测试如下: 成功了。
因此我们以后编写QSS文件时直接在vscode上编写就可以了,然后再加载进Qt程序中。
然后选择运行就行。
选择器
关于选择器的概念与CSS类似。
CSS 选择器规定了 CSS 规则会被应用到哪些元素上,QSS同理。
选择器的类型:
选择器类型
选择器 | 示例 | 描述 |
---|---|---|
通用选择器 | * | 匹配所有控件 |
类型选择器 | QPushButton | 匹配给定类型控件,包括子类 |
类选择器 | .QPushButton | 匹配给定类型控件,不包括子类 |
属性选择器 | QPushButton[flat=“false”] | 匹配给定类型控件中符合[属性]的控件 |
ID选择器 | QPushButton#closeBtn | 匹配给定类型,且对象名为closeBtn的控件 |
子孙对象选择器 | QDialog QPushButton | 匹配给定类型的子孙控件 |
子对象选择器 | QDialog>QPushButton | 匹配给定类型的直接子控件 |
辅助(子控件)选择器 | QComboBox::drop-down | 复杂对象的子控件 |
伪状态选择器 | QPushButton:hover | 控件的特定状态下的样式 |
并集选择器 | QPushButton,QCheckBox |
通用选择器
应用到所有的控件中,包括主窗口Widget
/*通用选择器*/
*{
background-color: red;
}
请注意:它的优先级是最低的,即如果我们给其他的控件已经设置了样式,则它就是我们设置的那样,如下图,我们已经给QLabel设置了样式了,因此会匹配为QLabel的样式,实际上刚刚我们的QLabel就是一个类型选择器,可以看到类型选择器比通用选择器的优先级高。
类型选择器与类选择器
它就是针对某个控件的样式设置,注意它包含子类。
即如果我们对QAbstractButton
设置了样式,则QPushButton
的样式也会改变,因为QPushButton继承自QAbstractButton。
/*类型选择器*/
QAbstractButton{
background-color: antiquewhite;
}
可以看到所有的按钮都被设置样式了。
对于类选择器,可以说他是真正的精准匹配的方式。
只需要在前面添加一个 .
号
/*类选择器*/
.QAbstractButton{
background-color: antiquewhite;
}
则子类的样式不会被改变,只会匹配具体的控件,显然QAbstractButton不是一个具体的控件。
属性选择器
对于某些按钮,如QPushButton的**checkable
**属性,我们可以设置这个按钮为无法选中状态,则我们就可以在这个状态设置样式:
/*属性选择器*/
QPushButton[checkable = 'true']{
background-color: chocolate;
}
我们首先为几个按钮指定以下这个checkable属性,则我们就会发现满足这个属性的控件的样式都被更改了。
ID选择器
如果我们指定了某个控件的ID名字,实际上就是这个变量的名字,则我们就可以使用ID选择器,
/*ID选择器*/
QPushButton#btn1{
background-color: fuchsia;
}
简单来说就是对**指定的控件变量
**设置样式。注意:ID是唯一的。
子孙对象选择器
匹配某个控件里的所有的第二个控件的子孙或其本身控件,
/*子孙对象选择器*/
QGroupBox QAbstractButton{
background-color: red;
}
可以看到QGroupBox中具有一个QPushButton
和QRadioButton
,他们都继承自QAbstractButton,因此我们可以看到在这个QGroupBox里面的这两个孩子控件都改变样式了。但是在QGroupBox之外的QPushButton却没有改变样式。
子对象选择器
匹配第一个控件里的所有第二个控件(精准匹配)
/*子对象选择器*/
QGroupBox QRadioButton{
background-color: darkgreen;
}
可以看到QGroupBox 里面的 **QRadioButton**
被改变样式了,但是QPushButton没有改变,因为是精准匹配。
辅助选择器
匹配某个控件的某个部位。
QComboBox:drop-down{
background-color: aqua;
}
在这里我们专门匹配了QComboBox的**下拉框drop-down
**,因此它会匹配某个复杂控件的具体部位,关于这些小部位的名称我们下面在介绍专门的控件美化的时候会说。
伪状态选择器
状态 | 描述 |
---|---|
:disabled | 控件禁用 |
:enabled | 控件启用 |
:focus | 控件获取输入焦点 |
:hover | 鼠标在空间上悬停 |
:pressed | 鼠标按下 |
:checked | 控件被选中 |
:unchecked | 控件没有选中 |
:indeterminate | 控件部分被选中 |
:open | 控件 |
:closed | 空间关闭 |
:on | 控件可以切换,且处于on状态 |
:off | 控件可以切换,且处于off状态 |
! | 对以上状态的否定 |
简单的使用:
鼠标悬停:hover
,鼠标按下:pressed
QPushButton:hover{
background-color: antiquewhite;
}
如下展示了鼠标悬停与按下时候的样式变化
控件的美化
QLabel
字体
QLabel
{
/*分开设置*/
/*font-family: "楷体";
font-size: 20px;
font-style: italic;
font-weight:bold ;
/*快捷设置*/
font:bold italic 18px "微软雅黑";
color:cornflowerblue;
}
- font-family 为设置字体类型,标准形式需要加双引号,不加也可能会生效,具体看系统是否支持,中英文都支持,但要保证字体编码支持,一般程序编码为"utf-8"时没问题。
- font-size 为设置字体大小,单位一般使用 px 像素
- font-style 为设置字体斜体样式,italic 为斜体, normal 为不斜体
- font-weight 为设置字体加粗样式,bold 为加粗, normal 为不加粗
- font 为同时设置字体 style weight size family 的样式,但是 style 和 weight 必须出现在开头,size 和 family 在后面,而且 size 必须在 family 之前,否则样式将不生效,font 中不能设置颜色,可以单独设置 style weight 和 size,不能单独设置 family
- color 为设置字体颜色,可以使用十六进制数表示颜色,也可以使用某些特殊的字体颜色:red, green, blue 等,或者使用 rgb(r,g,b) 和 rgba(r,g,b,a) 来设置,其中 r、g、b、a 值为0~255,如果想不显示颜色可以设置值为透明 transparent
边距
即设置内边距padding的边距。
QLabel
{
padding-left: 10px;
padding-top: 8px;
padding-right: 7px;
padding-bottom: 9px;
}
- Tips
- 在 qss 中,属性 text-align 对 Label 是不起作用的,只能通过设置 padding 来实现文字的显示位置;一般 padding-left 相当于 x 坐标,padding-top 相当于 y 坐标,设置这两个就可以在任意位置显示了
边框
QLabel
{
/*分开设置*/
border-style: solid;
border-width: 2px;
border-color:darkgoldenrod;
/*快捷设置*/
border:2px solid red;
}
- border-style 为设置边框样式,solid 为实线, dashed 为虚线, dotted 为点线, none 为不显示(如果不设置 border-style 的话,默认会设置为 none)
- border-width 为设置边框宽度,单位为 px 像素
- border-color 为设置边框颜色,可以使用十六进制数表示颜色,也可以使用某些特殊的字体颜色:red, green, blue 等,或者使用 rgb(r,g,b) 和 rgba(r,g,b,a) 来设置,其中 r、g、b、a 值为0~255,如果想不显示颜色可以设置值为透明 transparent
- border 为同时设置 border 的 width style color 属性,但值的顺序必须是按照 width style color 来写,不然不会生效!
圆角边框
QLabel
{
border-left: 2px solid red;
border-top: 2px solid black;
border-right: 2px solid blue;
border-bottom: 2px solid yellow;
border-top-left-radius: 20px;
border-top-right-radius: 15px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 5px;
/*border-radius: 20px;*/
}
- border-top-left-radius 为设置左上角圆角半径,单位 px 像素
- border-top-right-radius 为设置右上角圆角半径,单位 px 像素
- border-bottom-left-radius 为设置左下角圆角半径,单位 px 像素
- border-bottom-right-radius 为设置右上角圆角半径,单位 px 像素
- border-radius 为设置所有边框圆角半径,单位为 px 像素,通过圆角半径可以实现圆形的 Label
背景图片及样式
QLabel
{
background-color: #2E3648;
background-image: url("./image.png");
background-repeat: no-repeat;
background-position: left center;
/*background: url("./image.png") no-repeat left center #2E3648;*/
}
- background-color 为设置背景颜色,可以使用十六进制数表示颜色,也可以使用某些特殊的字体颜色:red, green, blue 等,或者使用 rgb(r,g,b) 和 rgba(r,g,b,a) 来设置,其中 r、g、b、a 值为0~255,如果想不显示颜色可以设置值为透明 transparent
- background-image 为设置背景图片,图片路径为 url(image-path)
- background-repeat 为设置背景图是否允许重复填充背景,如果背景图片尺寸小于背景实际大小的话,默认会自动重复填充图片,可以设置为 no-repeat 不重复,repeat-x 在x轴重复,repeat-y 在y轴重复
- background-position 为设置背景图片显示位置,只支持 left right top bottom center;值 left right center 为设置水平位置,值 top bottom center 为设置垂直位置
- background 为设置背景的所有属性,color image repeat position 这些属性值出现的顺序可以任意
QPushButton
QPushButton
{
/*1*/
border:none; /*去掉边框*/
border-radius:10px;
/*1,添加图片*/
background-image: url(图片路径);
background-repeat:none;
background-position:center;
/*3,把图片作为边框,会自动铺满背景*/
border-image: url(图片路径);
}
QPushButton:hover
{
background-color:rgba(102,205,227,255);
}
QPushButton:pressed
{
background-color:rgb(48,188,218);
}
QCheckBox、QRadioButton
QCheckBox{
color:red;
}
QCheckBox::indicator
{
width:16px;
height:16px;
border-image: url(:/images/checkBox/checkbox-unchecked.png);
border-radius:5px;
}
QCheckBox::indicator:checked
{
border-image: url(:/images/checkBox/checkbox-checked.png);
}
QCheckBox::indicator:unchecked:hover{
border-image: url(:/images/checkBox/checkbox-unchecked-hover.png);
}
QCheckBox::indicator:checked:hover{
border-image: url(:/images/checkBox/checkbox-checked-hover.png);
}
QGroupBox
QGroupBox {
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #E0E0E0, stop: 1 #EEEEEE);
border: 2px solid gray;
border-radius: 5px;
margin-top: 10px; /* leave space at the top for the title */
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top center; /* position at the top center */
padding: 2px 3px;
color: white;
margin-top: 2px;
background-color: gray;
border-radius: 3px;
spacing: 5px;
}
QGroupBox::indicator {
width: 13px;
height: 13px;
border: 1px solid black;
background: white;
}
QGroupBox::indicator:checked {
background: yellow;
}
QComboBox
QComboBox {
color: black;
border:1px solid black;
border-radius:5px;
padding: 1px 1px 1px 1px; /*不加这个圆角会有缺失*/
}
QComboBox::drop-down
{
width:25px;
border-image: url(:/images/comboBox/drop-down.png);
}
QComboBox::drop-down:hover
{
border-image: url(:/images/comboBox/drop-down-hover.png);
}
/*把checked换成on也行*/
QComboBox::drop-down:checked
{
border-image: url(:/images/comboBox/drop-down-on.png);
}
QComboBox::drop-down:checked:hover
{
border-image: url(:/images/comboBox/drop-down-on-hover.png);
}
/*设置下拉菜单的样式*/
QComboBox#usernameEdit QAbstractItemView
{
border: none;
background-color: rgb(255, 255, 255);
outline:0px ;
}
/*设置下拉菜单的每一项的样式*/
QComboBox#usernameEdit QAbstractItemView::item
{
height: 50px;
/*设置高度不生效,需要给QcomboBox设置如下属性(二选一)
//1,usernameEdit->setItemDelegate(new QStyledItemDelegate);
//2,usernameEdit->setView(new QListView
*/
}
QSpinBox、QTimeEdit、QDateEdit、QDateTimeEdit
QSpinBox 的 subcontrol 有 ::up-button
, ::down-button
, ::up-arrow
, ::down-arrow
。
- up-button 显示在 QSpinBox 里,它的 subcontrol-origin 是相对于 QSpinBox的
- down-button 显示在 QSpinBox 里,它的 subcontrol-origin 是相对于 QSpinBox的
- up-arrow 显示在 up-button 里,它的 subcontrol-origin 是相对于 up-button 的
- down-arrwo 显示在 down-button 里,它的 subcontrol-origin 是相对于 down-button 的
QSpinBox
{
border:1px solid black;
border-radius:5px;
}
/*按钮*/
QSpinBox:down-button,QSpinBox:up-button
{
width:16px;
height:15px;
subcontrol-origin:padding;
background:white;
border:2px solid rgb(217,217,217);
border-radius:5px;
}
QSpinBox:down-button
{
subcontrol-position:left center;
}
QSpinBox:up-button
{
subcontrol-position:right center;
}
QSpinBox:down-button:hover,QSpinBox:up-button:hover
{
border:2px solid rgb(138,138,138);
}
/*箭头*/
QSpinBox:down-arrow
{
border-image: url(:/images/spinBox/down-arrow.png);
}
QSpinBox:up-arrow
{
border-image: url(:/images/spinBox/up-arrow.png);
}
QSpinBox:down-arrow:hover
{
border-image: url(:/images/spinBox/down-arrow-hover.png);
}
QSpinBox:up-arrow:hover
{
border-image: url(:/images/spinBox/up-arrow-hover.png);
}
QSlider
QSlider 的 subcontrol 有 ::groove
(槽),::handle
,::add-page
和 ::sub-page
。
- groove 显示在 QSlider 里,它的 subcontrol-origin 是相对于 QSlider 的
- handle 显示在 groove 里,它的 subcontrol-origin 是相对于 groove 的
- sub-page 显示在 groove 里,它的 subcontrol-origin 是相对于 groove 的
- add-page 显示在 groove 里,它的 subcontrol-origin 是相对于 groove 的
- handle, sub-page, add-page 虽然都显示在 groove 里,但是都可以把它们扩展到 groove 外
QSlider::groove:horizontal
{
border: 1px solid skyblue;
background-color: skyblue;
height: 10px;
border-radius: 5px;
}
QSlider::handle:horizontal
{
background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0.7 white,stop:0.8 rgb(143,212,255));
width: 20px;
border-radius: 10px;
margin-top: -5px;
margin-bottom: -5px;
}
QSlider::sub-page:horizontal
{
background: #999;
margin: 5px;
border-radius: 5px;
}
QSlider::add-page:horizontal
{
background: #666;
margin: 5px;
border-radius: 5px;
}
QProgressBar
对于 QProgressBar 的 QSS,大多数都是想把 chunk 定义为圆角矩形的样子,但是当它的 value 比较小时,chunk 的圆角会变成直角,即使使用图片都不行,效果很不理想,所以如果要修改 QProgressBar 的外观的话,推荐继承 QProgressBar 自己绘制或者使用 QStyle。
/*边框*/
QProgressBar
{
border:1px solid skyblue;
border-radius:5px;
height:5px;
text-align: center;
}
/*进度条*/
QProgressBar::chunk
{
background-color: steelblue;
border-radius: 5px;
}
QProgressBar
{
border-color: 1px solid blue;
border-radius: 5px;
text-align: center;
}
QProgressBar:chunk
{
background-color: aqua; /*设置快的颜色*/
width: 5px; /*块的宽度*/
margin: 0.5px; /*让每个块之间有点间隔*/
}
如果最大值和最小值都为0,则会显示一个繁忙提示,等待系统容错处理结束,再继续恢复加载
progressBar->setRange(0,0);