不能不懂的QSS(一)

QSS,全称Qt Style Sheets,讲中文就是Qt样式表,后面我们都简称样式表,还有一个层叠样式表CSS,做网页用的,是QSS的父类。
做Qt开发的,不懂样式表,就好比一个人没穿衣服在大街上走,你总得穿上衣服吧。穿衣服,注意最好不要只动眼看,河水深与浅,哪些地方有坑,只有过了河的人才知道,心到,眼到,手到,缺一不可。
本文章为个人系统性总结笔记,水平有限,错误的地方,漏掉的地方还请各位大侠指正

样式表是啥?

样式表是啥?它是干嘛的?样式表是一种让你的身体与衣服独立的机制。程序开发完了,就好比婴儿出生,光溜溜的来到这个世界,当你给它套上样式表后,它才穿好了衣服,可以去见你的客户了。
我们一般人都有以貌取人的倾像,客户也一样。也许你的水平很高深,但你的程序灰不溜湫,想必你自己也很难提起胃口,更别说挑剔的客户了。你水平不高,但是程序界面让人看了就爱不释手,客户也会认为你水平高。这种转变,就是样式表的作用,人都是愿意为他受不释手的东西付出人民币的,所以,它,咱不得不会。

如何使用样式表

方法一: 在代码中,通过使用控件的setStyleSheet()进行设置
方法二:在qtcreator的图片编辑器中,点右键直接设置样式表:

在这里插入图片描述
方法三:编写qss文件,通过使用Qapplication的setStyleSheet()进行设置.
方法四:使用命令行参数"-stylesheet"来指定要加载的QSS文件,如:./qt_demo -stylesheet test.qss
推荐使用方法三,原因如下:
方法一:维护不便,总不能领导叫我换一个风格,我一个一个去搜索再修改吧
方法二:虽然所见即所得,存在子控件会继承父控件样式问题,另外也不方便维护.
存在即是合理,就像goto语句一样,三种方法各有优缺点,从方便维护角度考虑,推荐方法三.

备注:三种方法其实是一样的,本质都是调用了setStyleSheet接口,方法二中的图形化设置方法,通过查看ui***.h,可以知道它实际也是调用的这个接口.

如何编写样式表

语法规则
1. 类名、对像名、属性名大小写敏感,其它均敏感,这一条等于没有,反正编写时,均按大小写敏感的来,养成良好的习惯,少躺一点坑。
2. 声明一定要用分号结束,切记。什么是声明?不明白继续往后看就知道了,先别纠结。
3. 注释必须是/**/,且不支持嵌套,注意了,不能嵌套
4. 每一处样式描述分均由选择器字段和一对大括号组成,括号可以直接跟在选择器字段后,也可以另起一行
5. 最后一句声明,可以不以“;”结束,其它均要求“;”结束,否则运行时才会报错,注意了是运行时。
#widget{
background-image: url(":/new/prefix1/folder.png"); /这里一定要分号/
background-repeat: repeat-x; /这里可要可不要,建议一起加上/
}
6. 其它待补充

基本名称

 选择器(selector);你所设置的样式,对谁起效。
 辅助控制器(sub-control);有些控件由两部分组成,一半文本一半控件,如RadioButton,它的控件部分就是辅助控制器。
 状态(pseudo-states),控件处在什么状态样式表是什么样的,最典型的代表就是按钮,有三种状态,正常、悬浮、按下。
 属性与值;样式表的最终落实项就是对指定的属性进行设值,如颜色是哪个,边框线条多少像素等。
总体关系见下图:
在这里插入图片描述

盒子模型

在这里插入图片描述
使用样式表时,所有的控件都被视为一个同心四个矩形的集合体。如上图所示,默认四个矩形属性都是0。
margin:控件边框留白,默认是0,不留白,所以这个正常是看不到的,但我们能通过对比发现它:
在界面上放8个标签,分成两排,注意上下两排紧邻,在样式表中设置:
#label,#label_test2,#label_test3,#label_test4 {
margin:0px 0px 0px 0px;
background-color:red;
}
#label_test5 {
margin:12px 0px 0px 0px;
background-color:red;
}
#label_test6 {
margin:0px 12px 0px 0px;
background-color:red;
}
#label_test7 {
margin:0px 0px 12px 0px;
background-color:red;
}
#label_test8 {
margin:0px 0px 0px 12px;
background-color:red;
}
先不管为啥这么写,程序运行后的实际效果如下:
在这里插入图片描述
边框留白按上右下左进行了变化,如果没有对比,根本就看不出改变margin的效果。
border:边框矩形,默认边框像素为0,因此也看不见,设置样式表如下:
#label{
border: 2px solid green;
background-color:yellow;
}
实际效果:
在这里插入图片描述
注意border写法,不写像素大小2px或线型solid,边框都会看不见。
padding: 对内容周围进行填充,默认是0,也就是不进行填充,我们测试如下:
#label,#label_test2,#label_test3,#label_test4{
padding: 0px 0px 0px 0px;
background-color:red;
}
#label_test5 {
padding:12px 0px 0px 0px;
background-color:red;
}
#label_test6 {
padding:0px 12px 0px 0px;
background-color:red;
}
#label_test7 {
padding:0px 0px 12px 0px;
background-color:red;
}
#label_test8 {
padding:0px 0px 0px 12px;
background-color:red;
}
实际效果:
在这里插入图片描述
可以看到,第一排文字位置没有变动,第二排就可以发现也是按上右下左的顺序在进行变动。所以,以后若发现文字与标签左侧顶起了,想要加一点点距离,就不用在文字前面加空格了,直接改样式表就可以了。
综上所述,可以将盒子模型理解为在边框外留白,在边框内填充里面再套内容的线宽为0的矩形。

选择器

选择器类型有如下几种:
在这里插入图片描述
摸一把石头:
在这里插入图片描述
可以见到,经过*选择器后,所有的控件字体颜色都变红,再添加了类型选择器后,按钮的颜色变成了蓝色。
在这里插入图片描述
因为标签是QFrame的子类,所以这里我特意放了这两个来进行测试,可以看到,界面中的Qframe和Qlabel边框都变粗了。
在这里插入图片描述
可以看到“标签1”这个位置的变化。
在这里插入图片描述
Id选择器,类名#控件名,类名可以省略,即写成#pushButton。
在这里插入图片描述
组选择器是不是叫组合选择器更贴切?它根本就不是一种选择器,而只是一种语法方法而矣。
在这里插入图片描述
后代选择器,选定指定父类中的子类控件,所以“标签2”、“标签3”字体颜色变成了红色。为什么叫后代选择器,看下图:
在这里插入图片描述
如果只想要设置某个控件下指定的子控件样式,则可以使用子选择器。父对像与子对像之间用大于号“>”隔开。
在这里插入图片描述
动态属性选择器,需要代码配合,这里以label为例:
ui->label->setProperty(“state”,“true”);
ui->label->style()->unpolish(ui->label);
ui->label->style()->polish(ui->label);
样式表:
/动态属性选择器/
#label[state = “true”] {
color:red;
}

伪选择器

当伪状态与选择器结合,就是一个伪选择器,它匹配的是当某一控件处在某一状态时该是什么样子。为什么叫伪状态?我也不知道,英文名称就是pseudo-states,不纠结它,伪状态用“:”跟在选择器后,如:
QPushButton:hover { color: red } /鼠标进入时字体为红色/

伪状态选择器

不明白为什么叫伪状态,我们估且就按我们的理解叫状态算了。这个状态是指控件在交互时所处的状态,如按钮的hover状态等,qt助手中的Qt Style Sheets Reference章节有详细的描述,此处对助手中的描述进行实操,常用的状态如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
与位置相关的一些状态:
在这里插入图片描述
其它状态:
在这里插入图片描述
在这里插入图片描述

伪状态的与或非

这么多状态,当处在这个状态就意味着我不处在另外一个状态,要匹配这种“不处在这个状态”,我们需要用“!”进行匹配,如当某个控件鼠标没有处在hover状态时,将字体设置为红色:
QRadioButton:!hover { color: red }
这个“!”表示的,就是取反,和我们平常的逻辑取反一样。这些状态还支持与操作,直接将状态用“:”连接即可,如:
QCheckBox:hover:checked { color: green }
当QcheckBox被选中且鼠标hover时,字体显示绿色。状态也可以是取反过来的状态,如写成这样:
QCheckBox:hover:!checked { color: green }
或操作,则直接用“,”表示,如
QCheckBox: pressed,QCheckBox:hover:checked { color: green }

子控件

一个控件通常包含一个或多个子控件比如QcomboBox的下接按钮。当样式表描述这些子控件的外观时,必须要通过对应的选择器进行部件匹配,子控件通过“::”跟接在选择器的后面,Qt包含的子控件如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这些子控件,你可能想它们都长啥样,都在哪些位置?这里我们先了解就好,知道有这么一个东西,后面具体到控件时会直接标明。
子控件选择器通常需要参考另一个元素进行定位,这个参考元素可以是一个组件也或以是另一个子控件。例如下拉框QcomboBox的下拉按钮,本身默认是放在盒子模型的padding矩形的右侧,如果要将下拉按钮放到border矩形,可以通过subcontrol-origin对原点进行改变:
#comboBox_test,#comboBox_test_2,#comboBox_test_3,#comboBox_test_4 {
margin-right: 0px; margin-left: 0px;
}
#comboBox_test::drop-down { width:12px; height:12px; subcontrol-origin: margin;}
#comboBox_test_2::drop-down { width:12px; height:12px; subcontrol-origin: border;}
#comboBox_test_3::drop-down { width:12px; height:12px; subcontrol-origin: padding;}
#comboBox_test_4::drop-down { width:12px; height:12px; subcontrol-origin: content;}
实测效果:
在这里插入图片描述
除了看到下拉按钮位置有点点变化外,其它也看不出啥。
注意: margin左右必须要设置,数值为0也可以,但不能没有,后面会有说明。另外只有将下拉箭头大小宽高指定后才能看出位置的变化。

子控件的定位

如何确定子控件在父对像中的位置,有两种方式,相对和绝对定位,默认为相对定位,可以通过属性position来指定定位方式。

相对定位

相对定位适合于子控件具有固定大小的情形(可以通过width和height指定子控件大小)。它可以让子控件对subcontrol- position和subcontrol-origin属性定义的初始位置进行调整。使用left属性可以把子控件向右移,right属性可以把子控件向左移。确定没有写错,真的是left向右移,right向左移,top向下移,bottom向上移,不信请看下面示例:
#comboBox_test_4,#comboBox_test_5,#comboBox_test_6{ margin-right: 0px; margin-left: 0px;}
#comboBox_test_4::drop-down { position: relative; width:12px; height:12px; subcontrol-origin: content; subcontrol-position: center bottom;}
#comboBox_test_5::drop-down { position: relative; width:12px; height:12px; subcontrol-origin: content; subcontrol-position: center center; top:4px; left: 12px}
#comboBox_test_6::drop-down { position: relative; width:12px; height:12px; subcontrol-origin: content; subcontrol-position: center center; bottom:4px; right: 12px}
实测效果:
在这里插入图片描述
为什么这个移位会是反的?答案是相对,它相对左边移动正数值,当然是向右移了,这个left标明的是相对谁而不是移向谁。通过这个示例,也解决了一个疑问,相对,到底对着谁?可以看到,对的是subcontrol-position指定的对齐位置。

绝对定位

绝对定位适合于子控件的位置随父部件的变化而变的情形。subcontrol-origin指定父对像的参考矩形。子控件可以通过相对于这个参考矩形四边的偏移量来定义,如果是bottom,则参照的是参考矩形的底部,而不是相对定位中的对齐位置。但是如果子控件的大小是固定的,这个参照的位置会是参考矩形中subcontrol-position指定的对齐位置。
还用上面的那个例子,将position改为absolute,查看效果:
在这里插入图片描述
可以看到,和相对定位效果没有任何区别,再去掉width和height两个属性,效果出来了:
#comboBox_test_4,#comboBox_test_5,#comboBox_test_6{ margin-right: 0px; margin-left: 0px;}
#comboBox_test_4::drop-down { position: absolute; subcontrol-origin: content; subcontrol-position: center center;}
#comboBox_test_5::drop-down { position: absolute; subcontrol-origin: content; subcontrol-position: center center; left: 12px}
#comboBox_test_6::drop-down { position: absolute; subcontrol-origin: content; subcontrol-position: center center; right: 12px}
在这里插入图片描述
这个区别算明显了,只有定位方式不同,语言的表达不一定清楚,但是现像能告诉你一切。
好,现在,我们已知道了有哪些东西,如何去匹配它们,接下来就应该是如何去描述它们了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值