QT提供了QSS(QT Style Sheet)样式表来方便的自定义控件的外观来制作美观的程序界面,其语法与CSS类似
本文从以下几个方面介绍如何应用QSS
目录
一、如何加载QSS
二、常用控件的QSS
三、QSS的选择器
四、QSS冲突
五、自定义QSS属性
六、在运行时根据状态属性加载不同的QSS
常用的有三种方法:
1、统一加载QSS文件,应用于整个程序的控件
在main函数中
QApplication a(argc, argv);
a.setStyleSheet(style);//style: "QPushButton{background-color:transparent;}"
设置一些出现不多,在不同场合样式一样的控件的样式表,比如scrollBar,只需编写一次QSS就可以全局应用,但是如果时QpushButton这种出现频次多并且在不同场合样式不同的控件时,需要使用选择器用控件名称来选择特定的控件(比如QPushButton#closeButton{}),或者用下面两种方法单独设置样式表
2、在设计界面右击控件选择样式表,在其中编写
编写的样式表会应用到这个控件及其所有子控件
3、在代码中设置单个控件(及其子控件)的样式表
widget.setStyleSheet(style);//style: "QPushButton{background-color:transparent;}"
4、此外,QWidget默认不支持QSS,如果我们继承自QWidget建立一个自定义控件,需要重写其paintEvent()方法在其中添加对QSS的支持
void CustomWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
QPushButton
{
/*背景颜色
颜色可以用颜色代码例如#9eea6a表示
也可以用rgb(255, 255, 255)表示
透明使用transparent
*/
background-color:transparent;
/*
字体设置
*/
font: 10pt "微软雅黑 Light";
/*
边界设置
*/
border:1px solid red;
/*圆角*/
border-radius:15px
/*
设置背景图片,图片大小无法改变
*/
background-image: url(:/icons/expression16px#515151.png);
/*
背景的位置设置
*/
background-origin:content;
background-position:center;
/*
背景图片不重复
*/
background-repeat:no-repeat;
}
/*滚动条样式*/
/*选择器选择垂直滚动条vertical(的背景)*/
QScrollBar:vertical {
background:transparent;
/*宽度*/
width:9px;
/*边距*/
margin: 0px 0px 0px 0px;
}
/*选择器选择垂直滚动条(的滚动滑块)*/
QScrollBar::handle:vertical {
background: rgb(195, 195, 195);
/*最小长度,因为随着列表项增大增多滑块会变短,设置一个不能再变短的极限长度*/
min-height: 20px;
/*圆头滑块*/
border-radius: 3px;
}
/*选择器选择垂直滚动条的滑块的鼠标悬停时的背景*/
QScrollBar::handle:vertical:hover{
background:rgba(0,0,0,30%);
}
1、QPushButton 匹配所有该类及该子类件实例
2、.QPushButton 匹配仅仅该类实例
3、QPushButton[state='something'] 匹配该类及子类state属性为something的实例,这里的属性是可以用setProperty自定义的属性
4、QPushButton#closeButton 匹配objectName为'closeButton'的该类及其子类实例
5、QDialog QPushButton 匹配QDialog及其子类实例中包含(children)的所有QPushButton及其子类实例
6、QDialog > QPushButton 匹配QDialog及其子类实例中直接包含(children)的所有QPushButton及其子类实例
7、QScrollBar::handle 复合控件中选择handle
最常用的大概就是QPushButton的伪状态了:
QPushButton:hover 鼠标悬停
QPushButton:press 鼠标按下
此外Qt预设控件的伪状态用到时再查询即可
1、因为控件的嵌套产生一个控件实例被应用多个样式表时,比如最靠近该实例的样式表会被应用。例如在程序Application上应用QPushButton样式,又在单独的按钮上应用样式表,有冲突的部分会采用单独应用的样式表。
2、QPushButton{} 与QPushButton:hover{} QPushButton[state='']、QPushButton#closeButton{} 起了冲突,应用后面三个
3、那么如果是QPushButton:hover{} 与QPushButton#closeButton{}冲突了该怎么办呢
CSS中引入了“权重”的概念处理冲突,QSS与之相同,这里记录下
1.计算一条规则中id选择器的个数,假设存放在变量a中
2.计算一条规则中类选择器和属性选择器的个数,存放在变量b中
3.计算一条规则中的类型选择器的个数,存放在变量c中
4.忽略伪元素,对应QSS中的子控件
先比较a再b最后c
这样一看,QPushButton:hover{} 与QPushButton#closeButton{}冲突了要应用后者,测试了一下,确实如此
对于自定义控件, 要想用样式表设置自定义的属性,需要用宏Q_PROPERTY()注册自定义属性,例如:
QColor customColor;
Q_PROPERTY(QColor customColor READ getMesBorderColor WRITE setMesBorderColor RESET resetMesBorderColor)
MOC会帮助我们完成剩下的工作,我们已经可以开始用样式表设置这个属性了(假设我们的自定义控件为CustomWidget):
CustomWidget
{
qproperty-customColor:transparent;
}
如果自定义属性是枚举类型,需要额外一些操作:
public:
enum CustomEnum
{
Sunday,
Monday
}
CustomEnum enumProperty;
Q_ENUMS(CustomEnum)
Q_PROPERTY(CustomEnum enumProperty READ getEnumProperty WRITE setEnumProperty RESET resetEnumProperty )
现在可以在样式表中设置这个属性了
{
qproperty-enumProperty:"CustomWidget::Sunday";
}
另外,在代码中使用自定义属性时,最好repolish下重载下以求得到此时此刻正确的属性值
auto repolish=[](QWidget *w){
w->style()->unpolish(w);
w->style()->polish(w);
};
在实现自定义控件时有事希望控件在不同情况下出现不同外观,而这些情况用QSS自带的伪状态无法实现时,我们可以通过改变控件实例属性(setProperty())的方式。
比如在鼠标悬停在按钮上时改变另一个控件的外观,重写enterEvent()和leaveEvent()
auto repolish=[](QWidget *w){
w->style()->unpolish(w);
w->style()->polish(w);
};
void CustomButton1::enterEvent(QEvent*)
{
customBUtton2->setProperty("state","hover");
repolish(customBUtton2);
}
void CustomButton1::leaveEvent(QEvent *)
{
customBUtton2->setProperty("state","noHover");
repolish(customBUtton2);
}
样式表
CustomButton2[state='hover']
{
background-color:transparent;
}
CustomButton2[state='noHover']
{
background-color:Qt::red;
}
CustomButton2
{
background-color:Qt::red;
}