关于QT的QSS的知识总结

      用QT也一年多了,之前在做QSS这块没有仔细研究,总想着只要达到相应的效果就可以了,没有过分的细想。最近项目需要整体的美化一下,发现脑子对这方面一片空白。所以,现在来认真的总结下。

 

      样式表存在于一个文件中,QT的样式表统一拓展名为*.qss,用来存放样式和效果代码,然后通过QT程序的引用设置到整个程序中。例如:QPushButton{border:2px solid #8f8f91; border-radius:6px;}

 

Qt程序界面的定制有两种方法:

使用程序继承并实现一个QStyle的子类

Qt样式表的使用。

 

样式表的由来:仿照CSS样式表的模式对界面程序样式进行定制与修改。

  Qt样式表的思想很大程度上是来自于HTML的层叠式样式表(CSS),通过调用QWidget::setStyleSheet()QApplication::setStyleSheet()从而可以为一个独立的子部件、整个窗口,甚至是整个应用程序指定一个样式表。

样式表的程序引用:

       通过QStyle的一个叫做QStyleSheetStyle的特殊子类来实现的。这个特殊的子类实际上是其他的系统特定风格类的包裹类, 它会把通过样式表指定的自定义外观风格应用在底层的系统特定风格之上。

如何使用样式表?

 

1.样式表原理:方箱模型

    对于任何一个控件或者控件里的子部件,可以这样了理解,相对于下图,一个空间可以分为四个区域边框:

  Margin  :控件最外围的空白区域,总是透明的

  Border  :控件的外边框

  Padding:控件的外边空到内显示区域的空白区域

  Content:控件的最内显示区域

 

注意:当Margin大小为0时,控件大小就是显示的实际大小.

 

2.样式表基本语法:

一个样式表由一系列的样式规则构成。每个样式规则都有着下面的形式:

selector { attribute:value}

  选择器(selector)通常是一个类名(例如QComboBox),当然也还有其他的语法形式。

  属性(attribute)部分是一个样式表属性的名字,值(value)部分是赋给该属性的值。

selector #ObjectName{attribute:value}

  ObjectName是一个指定的控件的名字,一般由程序中调用setObjectName()来指定。

  注意:前一个的样式,会被后来的样式所覆盖

 

为了使用方便,我们还可以使用一种简化形式,这样:

     selector1, selector2, ..., selectorM{attribute1:value1;attribute2:value2;...attributeN:valueN}

如:

QCheckBox, QComboBox, QSpinBox{
         color: red;
         background-color: white;
         font: bold;

 }

 

当然也可以这样:
selector1#ObjectName1,selector2#ObjectName1, ..., selectorM #ObjectName1 {attribute1:value1; attribute2:value2; ... attributeN:valueN;}

  如:

  QCheckBox#MainCheckBox,QComboBox#MainComboBox  ,QSpinBox#MainSpinBox{

  color: red;  background-color: white;  font: bold;}

 

3.控件子控件了解:子部件微观样式化

界面是如何通过qss来定制不同的效果?为什么同一种控件可以产生不同的显示效果?这个就得从控件的构成开始说。

这是一个滚动条,如左图,控件名为QScrollBar,如图所示,有着很多的子控件,而每一个子控件都可以定制不同的效果,综合起来就成了一套效果。因此在进行QSS开发是需要了解的是某个控件分别有些什么子控件。下页是一些基本的字控件(sub-control)列表:

4.控件状态及效果分析:

  以下是几种常见的状态:

示例

 

5.控件大小等设定:

对某一个控件的大小进行调整很简单,使用widthheight进行调整即可,当然也可以添加min-max-前缀进行修饰,最小单位为像素(PX)用于调整界面整体效果,如:

QWidget#MainWindowsHeadBar {

            margin:0px;  //margin外框为0个像素

            border:2px solid red//border显示

            width: 36px;  //控件宽

            height: 23px;  //控件高

           border-image:url(IMAGE_PATH/minimize.png) 1; //图片

       }

当然这是控件大小?那么线条呢?呼~~~ 如上绿色字体:

  2px:线条为2个像素

  solid:实线

  red:红色

以下为线条border-style的可选项,可以参照如下:

 

 

其他:

 

 

border-radius:为设置圆角

border:1pxsolid transparent; //宽度为1px的透明实线(什么都看不到)

6.控件位置等排版

此模块主要介绍的是相对定位:

  位置排版就是通过微调界面控件显示位置进行排版,先给大家看两个效果,以MPRMaker For PDF为例:

效果一:slider控件效果

  使用后 使用前

效果一:设置对话框效果

  使用前:

  使用后:

QFrame{
  margin: 14px 18px 20px 18px;
}

  如上:进行位置偏移设置表示上右下左四个方向分别为14 1820 18个像素,同时,我们也可以分别指定margin-topmargin-rightmargin-bottommargin-left四个属性。

QFrame{
  margin-top: 14px;
  margin-right: 18px;
  margin-bottom: 20px;
  margin-left: 18px;
}

我们也可以同样的将这些属性应用于任何一个支持方箱模型的Qt部件,例 如:QCheckBoxQLabelQLineEditQListViewQMenuQPushButtonQTextEdit、和QToolTip,甚至也可以将其作用于子部件上。

同时,采取此方法能够实现按下弹起的状态,就是实现采用当鼠标按下动作的时候,让控件的显示位置向右下方移动几个像素,来模拟这个状态。

//MPRMaker PDF 工具栏Qcombobox下拉框按下动作效果实现

QToolBar#CommonToolBar  QComboBox::down-arrow:on {

    top: 1px;  

    left: 1px;  

7.控件图片等显示

设置某一个背景的图片,有如下三种方法:

1.background-image

2.background

3.border-image

4.image

区别:

  border-image:图片显示采取拉伸效果为默认缺省
  background-image:图片显示采取重复效果为默认缺省
  image:图片显示采取原图大小为默认缺省
  background:包含background-image

  1.background-imagebackground中的一种,background还包含其他属性,有colorrepeatposition等等;

  2.border-imagebackground-image,前者是在控件的border区域进行设置,后者是整体,包括margin区域,且同时设置,前者会覆盖在后者的图片之上。

  3. image不会改变图片大小

传说中的九宫格:实用性很强大~~先给个赞!如下:

了解:

  图片在实际的应用中,如果不使用九宫格方式,图片会进行自动复制重绘平铺显示或者进行对应比例的像素画放大,如果存在阴影等会出现阴影模糊,显示效果变差。而解决这个问题的方法就是九宫格。

原理:

    程序自动按照所分配的像素进行四边的切割,然后保留边界的图片数据,自动将中间的数据进行像素化拉伸。

使用举例:

   border-image:url(button.png) 4 4 4 4 stretch stretch;

//图片 上右 下 左 拉伸(缺省) 拉伸(缺省)

border-width4 4 44//必须有~

 

 

QSS总结以及最近做的Qt项目

阅读目录

回到顶部

什么是QSS

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

回到顶部

QSS在Qt程序中的使用办法

首先将QSS写在文件中,然后利用如下的代码设置QSS:

?

1

2

3

4

5

6

7

8

9

10

11

12

MainWidget::MainWidget(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::MainWidget)

{

  //应用样式 apply the qss style

    QFile file(":/qss/main.qss");

    file.open(QFile::ReadOnly);

    QTextStream filetext(&file);

    QString stylesheet = filetext.readAll();

    this->setStyleSheet(stylesheet);

   file.close();

}

该段代码写在ui界面的后台cpp文件的构造函数中,主要是this->setStyleSheet()函数的设置功能,要说明的是该函数除了可以对整个当前构造数所在的那个类所表示的ui进行整体应用样式以外,setStyleSheet()函数本身是QWidget的成员函数,几乎Qt中的大多数控件都可以直接使用该函数分别设置自己的样式。

回到顶部

QSS的语法规则

QSS的语法规则几乎与CSS相同。一条QSS的样式是由两部分组成的,一部分是选择器指定了哪些控件会受到影响,另一部分是指定了属性的值,表示这些控件的哪些属性会受到影响。例如:

QPushButton { color: red }

QPushButton表示选择器,指定了所有的QPushButton或者是QPushButton的子类会受到影响,注意凡是继承自QPushButton的子类也会受到影响,这是与CSS中不同的地方,因为CSS应用的都是一些标签,没有类的层次结构,更加没有子类的概念。而后面的{color:red}则是规则的定义,表明指定前景颜色是红色。整个意思就是设置QPushButton类以及其子类的所有实例的前景色是红色。

如果MyButton继承自QPushButton,那么上面的规则也会应用到所有MyButton控件上,但是如果规则是如下的:

MyButton{color:red} 

则只会对MyButton的实例应用红色的前景颜色,而对QPushButton的实例没有应用。

回到顶部

QSS的选择器类型

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

另外上面所有的这些选择器可以联合使用,并且支持一次设置多个选择器类型,用逗号隔开,这点与CSS一样,例如#frameCut,#frameInterrupt,#frameJoin 表示所有这些id使用一个规则。#mytable  QPushButton 表示选择所有id为mytable的容器下面的QPushButton实例

回到顶部

QSS子控件

QSS的子控件实际上也是选择器的一种,因为这种选择器与CSS有一些不同,所以单独拿出来说,QSS的子控件选择器是应用在一些复合控件上的,典型的例如QComboBox,该控件的外观包含几个部分,一般情况下有一个矩形的外边框,右边有一个向下的箭头用于提示点击之后会有弹出下拉列表。例如:

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

上面的样式指定所有QComboBox的下拉箭头的图片为自定义的图片dropdown.png
::dropdown子控件选择器也可以与上面提到的选择器一起联合使用:

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

指定id名为myQComboBox的QComboBox控件的下拉箭头的自定义图片,要注意的是子控件选择器实际上是选择复合控件中的一部分,也就是说对复合控件中的一部分应用样式,例如为QComboBox的下拉箭头指定图片,而不是为QComboBox本身指定图片。

QSS为很多复杂的复合控件提供了子控件的定义,以方便对这些复合控件的各个部分进行样式设置。限于篇幅,本文也不能将这些可用的子控件都列出来,在安装QtCreator之后自带的帮助中就有很详细的描述。

回到顶部

QSS伪状态

QSS的伪状态选择器实际上与CSS中的类似,是以冒号开头的一个选择表达式,例如:hover表示当鼠标经过时候的状态。他限制了当控件在某一种状态下的时候才能应用QSS规则,伪状态只能描述一个控件的状态,或者是一个复合控件中的子控件的状态,所以该伪状态选择器只能放在选择器的最后面,例如:

QComboBox:hover{background-color:red;}

该规则表示当鼠标经过QComboBox上面的时候,其背景颜色指定为红色,该伪状态 :hover描述的是QComboBox的状态。
伪状态除了描述选择器选择的控件以外,还可以描述子控件选择器所选择的复合控件中的子控件的状态,例如:

QComboBox::drop-down:hover{background-color:red;}

表示当鼠标经过QComboBox的下拉箭头的时候,该下拉箭头的背景颜色变成红色。
此外伪状态可以用一个感叹号表示否,例如:hover表示鼠标经过,而:!hover表示鼠标没有经过的状态。几个伪状态可以同时一起使用,例如:

QCheckBox:hover:checked { color: white }

指定一个当鼠标经过一个选中的QCheckBox的时候,设置其文字的前景颜色为白色。
QSS提供了很多的伪状态,一些伪状态只能用在特定的控件上,具体有哪些伪状态,在Qt的帮助里面有详细的列表,限于篇幅这里也不列出了。

回到顶部

QSS级联与冲突

QSS中的级联包含几个方面的概念,一个是当在同一个控件上应用两个不同的规则,那么应该应用哪一个规则的问题,也就是如何解决这种冲突。二个是在一个容器控件上设置的QSS规则会对容器里面的控件产生效果(这要取决于容器控件上设置的QSS规则是什么样的规则,如果容器控件上设置的QSS规则仅仅针对容器控件本身则该规则对子控件没有影响,如果该QSS规则里面有对子控件的设置,则自然会对子控件产生效果),级联问题是解决当一个控件被层层父容器包裹,并且在每一层的父容器上都有对该控件的样式设置的时候,该控件的最终效果是合并这些父容器上的QSS效果。

冲突问题:

?

1

2

QPushButton#okButton { color: gray }

QPushButton { color: red }

这两条规则都会应用到名为okButton的按钮上,但是他们为同一个属性设置了不同的颜色,这会有冲突,那么要解决这样的冲突就必须考虑到选择器的特异性(这个词怎么理解,我理解为这个特异性为更加特殊,实际上CSS上用权重表示这里的特异性),显然QPushButton#okButton仅仅针对对象名为okButton的控件有效果,而QPushButton却对所有的QPushButton的实例或者是其子类的实例有效果,显然QPushButton#okButton选择器更加特殊,也就是更具有特异性。所以最终okButton前景色被应用为灰色。如果两条规则的特异性一样,那么就选择放在后面的那一条。

另外如果一个选择器应用了伪状态,而另一个没有,那么应用了伪状态的选择器要更加特殊,例如:

?

1

2

QPushButton:hover { color: white }

QPushButton { color: red }

显然QPushButton:hover比单纯的QPushButton更加具有特异性。这两条规则表示当鼠标放在按钮上的时候文字是白色,其他情况下都是红色。
如下面两个规则的特异性是一样的,那么应该是如何应用呢:

?

1

2

QPushButton:hover { color: white }  //如果鼠标经过则前景白色

QPushButton:enabled { color: red }  //如果按钮是enabled状态则前景红色

所以默认情况下前景文字是红色的,当鼠标经过的时候并不会变成白色,因为他们的特异性是一样的,所以选择后面的,也就是红色。
那么换一下顺序会怎样呢:

?

1

2

QPushButton:enabled { color: red }  //如果按钮是enabled状态则前景红色

QPushButton:hover { color: white }  //如果鼠标经过则前景白色

当鼠标经过的时候,就变成白色的了,因为他们的特异性一样,所以选择后面的规则,也就是鼠标经过前景变成白色。
如果把其中的一条的特异性增加,例如:

?

1

2

QPushButton:hover:enabled { color: white }

QPushButton:enabled { color: red }

那么第一条的特异性比第二条大,所以应用第一条的规则。
另外一种特异性发生在类型选择器上:

?

1

2

QPushButton { color: red }   //应用在所有的QPushButton上

QAbstractButton { color: gray } //应用在所有的QAbstractButton上

而在类的继承结构上,QAbstractButton是QPushButton的父类,显然QPushButton更加具有特异性,所以QPushButton的前景颜色被应用为红色,而不是灰色。有没有一个办法来确定两条QSS规则的特异性大小呢,其实QSS使用的特异性的计算方法与CSS是一样的,详细可以参考CSS2的文档规范,这里还是简要的说明一下,特异性这个东西在CSS中一般被称为权重,权重越大的越优先使用,CSS的计算规则如下:

1.计算一条规则中id选择器的个数,假设存放在变量a中
2.计算一条规则中类选择器和属性选择器的个数,存放在变量b中
3.计算一条规则中的类型选择器的个数,存放在变量c中
4.忽略伪元素,对应QSS中的子控件

下面是具体的计算方法:

?

1

2

3

4

5

6

7

8

*             {}  /* 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.red   {}  /* a=0 b=1 c=3 -> specificity =  13 */

LI.red.level    {}  /* a=0 b=2 c=1 -> specificity =  21 */

#x34y        {}  /* a=1 b=0 c=0 -> specificity = 100 */

上面的计算规则是CSS的计算规则,同样可以应用的QSS上。

关于级联:


QSS可以设置在QApplication上,也可以设置在一个部件的容器部件上,也可以设置在子孙部件上,一个部件最终使用的样式效果是合并了他的所有父容器,祖父容器等上面设置的所有样式的结果,这些设置会进行叠加。如果在级联过程中发生了冲突,例如部件本身指定的前景颜色为绿色,而其父亲容器为其指定的前景颜色为红色,此时就选择部件本身设置的样式效果。例如:

?

1

2

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

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

第一条语句表示在QApplication上设置QPushButton的样式,而第二条语句表示在myPushButton对象上设置样式。最终结果会将myPushButton的前景颜色设置为蓝色。级联效果主要应用在当一个控件的样式在多个容器控件上都有设置的时候,该控件的最终效果是这些所有容器控件上效果的合并。级联规则在CSS中本身也是一个复杂的主题,如果大家感兴趣,还是需要自己参考CSS2的规范文档,本节仅仅是抛装引玉。


另外一个要提到的是,QSS中似乎为父容器控件本身设置的样式,并不会被子控件继承,例如如果QFrame中有一个QPushButton控件,那么如下的语句:

?

1

ui->frame->setStyleSheet("QFrame{ color: red; border:1px solid red }");

该语句仅仅为QFrame设置前景颜色以及边框的效果并不会应用到其里面的QPushButton上,如果是下面的语句则都可以:

?

1

2

ui->frame->setStyleSheet("QPushButton{ color: red; border:1px solid red }");

ui->frame->setStyleSheet("*{ color: red; border:1px solid red }");

回到顶部

QSS实际应用中要注意的地方

在使用QSS的时候遇到过一些坑,看似简单,但是如果不知道的话,还是很折磨人的:
<1>使用QSS设置边框无效,例如:

?

1

2

3

4

border:1px solid red; //Ok

border:solid 1px red; //Error

border:red 1px solid; //Error

border:red solid 1px; //Error

设置边框颜色和像素的时候,必须是第一种顺序,而CSS中是无所谓的,至于原因,我也不清楚,就是这么坑人。

<2> QSS设置宽高无效:
在QSS中设置宽高必须要使用 min-width和min-height,max-width,max-height来设置,用width和height设置是没有任何效果的。

<3>QComboBox的样式设置的问题:
QcomboBox是一个复杂的控件,QComboBox由3部分组成,一个是QComboBox的外框,里面有一个下拉按钮,这个按钮可以通过QComboBox::drop-down 来控制其位置,将其定义到QComboBox的左边而不一定是右边。另外在这个下拉按钮上面一般会有一个向下的箭头,这个箭头图像也是可以定制的,通过QComboBox::down-arrow来指定箭头的图像。

如果要控制QComboBox的弹出下拉列表的样式需要通过:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

QComboBox QAbstractItemView {

  //设置当点击下拉按钮之后弹出的下拉列表的样式,要注意的是这里的样式

  //仅仅只能设置弹出的整个下拉列表范围的矩形的样式,不能设置下拉列表

  //中的每一个下拉项的样式,例如不能设置每一个下拉项高度

}

QcomboBox{

  //设置未弹出下拉列表的样式

}

 

QComboBox QAbstractItemView::item {

//设置弹出下拉列表中的每一个下拉项的样式,这里的样式要想生效,必须先

//对QcomboBox做下面的设置

//QStyledItemDelegate* itemDelegate = new QStyledItemDelegate();

//combox->setItemDelegate(itemDelegate);   

}

回到顶部

Qt开发的程序的案例

前面一段时间用Qt开发了一个基于公司平台的视频导出与编辑工具,当作一个案例贴出来吧,还是有很多可以美化的地方,窗体的外框没有做任何美化处理,用QSS做起来其实还是蛮简单的,里面的页面按钮,文本框,分页功能等都用QSS设置过,其实这个软件的界面算是中规中矩的,要做成酷狗,360那种风格用QSS是完全没有问题的:

1

登录界面,里面用到了Qt提供的正则验证功能,如果输入的ip不符合规则,则根本输入不了,例如如果输入一个非法的字符,则文本框中没有反应

登录进去之后的主界面,一共有7个选项卡,每一个选项卡代表一个功能:

视频导出:导出web平台上的视频数据,包括文件,片头片尾,视频的索引,可以导出电影模式,资源模式,支持断点续传。
视频剪切:可以将视频中不需要的内容剪切掉
视频截取:截取视频中需要的部分
后期导播:对资源模式进行后期导播
创建片头片尾:傻瓜式的生成片头片尾的图片文件
合成片头片尾:将片头片尾的图片文件添加到一个视频的起始和结束
转码上传:将多种格式的视频文件转码成MP4文件并上传到web平台

1

视频导出功能,实际上是导出一个课件,该课件可能录制的有电影模式的视频,资源模式的视频,或者都有。功能介绍如下:

1

视频剪切对视频进行剪切处理:

1

对视频进行截取:

1

对资源模式进行后期导播:

1

创建自定义片头片尾(其实就是傻瓜式的让用户生成自定义图片),里面的文字可以拖动,可以键盘微调,可以修改:

1

合并片头片尾,将生成好的片头片尾图片,合并到一个mp4的开始和结尾处,可以指定片头片尾的图片文件,并指定在mp4开头或结尾显示的时间:

1

转码与上传:

1

程序里面的外观包括,下拉列表,文本输入框,按钮,表格,tab等都是使用QSS设置的。QSS参考了CSS,所有里面有一些属性是与CSS相同的,但并不是所有的CSS属性都能够在QSS中使用,也并不是所有的Qt控件都支持CSS的盒模型,Qt帮助中关于QSS的部分详细描述了可用的QSS属性列表,以及控件列表,伪状态列表,子控件列表,QSS中可用的图标列表,以及QSS属性值的单位列表,限于篇幅不可能将所有这些都详细列出来,其实在安装QtCreator之后的帮助文档中有详细的描述,其列表类似下面的图(描述了部分伪状态的说明):

1

 

以上就是QSS的基本知识,其中如果需要了解细节的相关知识可以去查询QSS的帮助手册!

/*此为楼主原创文章,如需转载请注明出处*/

     

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值