QT-样式表
Qt样式表是一个可以自定义部件外观的十分强大的机制﹐除了那些能够通过子类化QStyle更改的外观,其余的都可以使用Qt样式表来美化。Qt样式表的概念,术语和语法都受到了HTML的层叠样式表(Cascading Style Sheets, CSS)的启发,不过与CSS不同的是,Qt样式表应用于部件。Qt样式表介绍样式表可以使用QApplication: : setStyleSheet()函数将其设置
Qt样式表是一个可以自定义部件外观的十分强大的机制﹐除了那些能够通过子类化QStyle更改的外观,其余的都可以使用Qt样式表来美化。Qt样式表的概念,术语和语法都受到了HTML的层叠样式表(Cascading Style Sheets, CSS)的启发,不过与CSS不同的是,Qt样式表应用于部件。
Qt样式表介绍
样式表可以使用QApplication: : setStyleSheet()
函数将其设置到整个应用程序上,也可以使用QWidget::setStyleSheet()
函数将其设置到一个指定的部件(还有它的子部件)上。如果在不同的级别都设置了样式表,那么Qt会使用所有有效的样式表,这被称为样式表的层叠。下面来看一个简单的例子。
使用代码设置样式表
新建Qt Widgets应用,项目名称为mystylesheets,类名为Main Window基类为QMainWindow保持不变。建立好项目后进入设计模式,向界面上拖人一个Push Button和一个 Horizontal Slider,然后在 mainwindow.cpp文件中的构造函数里添加如下代码:
// 设置pushButton的背景为黄色
ui->pushButton->setStyleSheet("background:yellow");
// 设置horizontalSlider的背景为蓝色
ui->horizontalSlider->setStyleSheet("background:blue");
这样便设置了两个部件的背景色,可以运行程序查看效果。
不过像这样调用指定部件的 setStyleSheet()函数就只会对这个部件应用该样式表,如果想对所有的相同部件都使用相同的样式表,那么可以在它们的父部件上设置样式表。因为这里两个部件都在 MainWindow 上,所以可以为Main Window设置样式表。先注释掉上面的两行代码,然后添加如下代码:
setStyleSheet("QPushButton{background:yellow}QSlider{background:blue}");
这样,以后再往主窗口上添加的所有QPushButton部件和 QSlider部件的背景色都会改为这里指定的颜色。除了使用代码来设置样式表外,也可以在设计模式中为添加到界面上的部件设置样式表,这样更加直观。
在设计模式中设置样式表
先注释掉上面添加的代码,然后进入设计模式。在界面上右击,在弹出的级联菜单中选择“改变样式表”,这时会出现编辑样式表对话框,在其中输入如下代码:
注意,光标留在第一个大括号后。然后单击上面“添加颜色”选项后面的下拉箭头,则在弹出的列表中选择background-color项,如图所示。这时会弹出选择颜色对话框,可以随便选择一个颜色,然后单击OK按钮,则自动添加代码:
根据选择颜色的不同, rgb()中参数的数值也会不同。可以看到,这里设置样式表不仅很便捷而且很直观,不仅可以设置颜色,还可以使用图片,使用渐变颜色或者更改字体。相似的,可以再设置QSlider的背景色,添加完成后如图所示。在设计模式有时无法正常显示设置好的样式表效果,不过运行程序后会正常显示的。这里是在MainWindow界面上设置了样式表,当然,也可以按照这种方法在指定的部件上添加样式表。
对于自定义样式,样式表要比调色板强大很多。例如,可以通过设置QPalette::Button角色为红色来获得一个红色的按钮,但是,这并不能保证在所有风格中都可以正常工作,因为它会受到不同平台的准则和本地主题引擎所限制。不过,样式表就不受这些限制,样式表可以执行所有的那些单独使用调色板很困难或者无法执行的自定义操作。样式表应用在当前的部件风格之上,这意味着应用程序的外观会尽可能本地化。此外,样式表可以用来给应用程序提供一个独特的外观,而不用去子类化QStyle,这样就可以很容易地实现大多数应用程序中拥有的换肤功能。
Qt样式表语法
Qt样式表的术语和语法规则与HTML CSS基本相同,下面从几个方面来进行讲解。本节内容可以在帮助中通过The Style Sheet Syntax关键字查看。
样式规则
样式表包含了一系列的样式规则,每个样式规则由选择器( selector)和声明( decla-ration)组成。选择器指定了受该规则影响的部件,声明指定了这个部件上要设置的属性。例如:
QPushButton{color:red}
在这个样式规则中,QPushButton是选择器,{ color: red}是声明,其中,color是属性, red是值。
这个规则指定了QPushButton和它的子类应该使用红色作为前景色。Qt样式表中一般不区分大小写,例如, color , Color,COLOR和COloR表示相同的属性。只有类名,对象名和Qt属性名是区分大小写的。一些选择器可以指定相同的声明,使用逗号隔开,例如:
QPushButton, QLineEdit,QComboBox{color :red}
样式规则的声明部分是一些“属性:值”对组成的列表,它们包含在大括号中,使用分号隔开。例如:
QPushButton(color:red; background-color:white)
可以在Qt Style Sheets Reference关键字对应文档中的List of Properties 一项中查看Qt样式表支持的所有属性。
选择器类型
Qt 样式表支持css2中的所有选择器。表中列出常用的选择器类型
子控件
对于一些复杂的部件修改样式,可能需要访问它们的子控件,比如 QComboBox的下拉按钮,还有QSpinBox的向上和向下箭头等。选择器可以包含子控件来对部件的.特定子控件应用规则,例如:
QComboxBox::drop-down{image:url(dropdown.png)}
这样的规则可以改变所有QComboBox部件的下拉按钮的样式。Qt Style SheetsReference关键字对应帮助文档的List of Stylable Widgets一项中列出了所有可以使用的样式表来自定义样式的Qt部件,List of SubControls一项中列出了所有可用的子控件。
伪状态
选择器可以包含伪状态来限制规则在部件的指定状态上应用。伪状态出现在选择器之后,用冒号隔离,例如:
QPushButton:hover{color:white}
这个规则表明当鼠标悬停在一个QPushButton部件上时才被应用。伪状态可以使用感叹号来表示否定,例如,要当鼠标没有悬停在一个QRadioButton上时才应用规则,那么这个规则可以写为:
QRadioButton:!hover{color:red}
伪状态还可以多个连用,达到逻辑与效果。例如,当鼠标悬停在一个被选中的QCheckBox部件上时才应用规则,那么这个规则可以写为:
QCheckBox: hover:checked{color:white}
如果有需要,也可以使用逗号来表示逻辑或操作,例如:
QCheckBox : hover,QCheckBox;checked{color :white)
当然,伪状态也可以和子控件联合使用:
QComboBox :: drop- down: hover { image;url(dropdown_bright.png)}
Qt Style Sheets Reference关键字对应帮助文档的List of Pseudo-States一项中列出了Qt支持的所有伪状态。
冲突解决
当几个样式规则对相同的属性指定了不同的值时就会产生冲突。例如:
QPushButton# okButton(color:gray}
QPushButton {color:red}
这样,okButton的color属性便产生了冲突。
解决这个冲突的原则是:
-
特殊的选择器优先
。因为QPushButton# okButton一般代表一个单一的对象,而不是一个类所有的实例,所以它比QPushButton更特殊,那么这时便会使用第一个规则,okButton的文本颜色为灰色。 -
相似的,
有伪状态比没有伪状态优先
。如果两个选择符的特殊性相同,则后面出现的比前面的优先。Qt样式表使用CSS2规范来确定规则的特殊性。
层叠
样式表可以设置在QApplication上、父部件上或者子部件上。部件有效的样式表是通过部件祖先的样式表和QApplication上的样式表合并得到的。当发生冲突时,部件自己的样式表优先于任何继承的样式表,同样,父部件的样式表优先于祖先的样式表。
继承
当使用Qt样式表时,部件并不会自动从父部件继承字体和颜色设置。例如,一个QPushButton包含在一个QGroupBox中,这里对QGroupBox设置样式表:
qApp ->setStyleSheet("QGroupBox {color: red;}");
但没有对QPushButton设置样式表。这时,QPushButton会使用系统颜色,而不会继承QGroupBox的颜色。
如果想要QGroupBox的颜色设置到其子部件上,可以这样设置样式表:
aApp ->setStyleSheet( "QGroupBox,QGroupBox * { color: red;}");
设置QObject属性
从Qt 4.3开始,任何可设计的Q_PROPERTY都可以使用“qproperty-属性名称”
语法来设置样式表。例如;
MyLabel{ qproperty- pixmap:url(pixmap. png);}
MyGroupBox{ qproperty- titleColor: rgb(100,200,100);}
QPushButton{ qaproperty- iconSize: 20px 20px;}
自定义与换肤
盒子模型
自定义部件外观
下面继续在上面程序中进行更改。首先向项目目录中添加4张图片,然后再向项目中添加一个Qt资源文件(添加新文件),名称为myresource。建立完成后,先添加前缀“/image”(右键-add prefix),然后将项目目录中的几个图片添加进来,最后按下Ctrl+S保存。
然后进入设计模式,再次打开主界面的编辑样式表对话框,先清空以前的代码,再添加如下代码:
/****************主界面背景**************/
QMainWindow{
}
这里可以将光标放到第一个大括号后,然后在“添加资源”的下拉列表中选择background-image,在弹出的选择资源对话框中选择一张背景图片(注意:第一次打开资源对话框时,可能无法显示资源,需要按下左上角的“重新加载”图标),这样便可以自动添加使用图片的代码。然后再更改QPushButton和QSlider的样式代码,最终的代码为:
/****************主界面背景**************/
QMainWindow{
/*背景图片*/
background- image: url(:/image/ beijing01. png);
/***按钮部件***/
background - color: rgba(100,225,100,30);
/*边框样式*/
border-style:outset;
/*边框宽度为4像素*/
border-width:4px;
/*边框圆角半径*/
border-radius:10px;
/*边框颜色*/
border-color:rgba(255, 225,255, 30);
/*字体*/
font:bold 14px;
/*字体颜色*/
color:rgba(0, 0, 0, 100);
/*填衬*/
padding: 6px;
}
/*鼠标悬停在按钮上时*/
QPushButton:hover{
background-color:rgba(100,255,100,100);
border-color:rgba(255, 225, 255,200);
color:rgba(0, 0, 0, 200);
/*按钮被按下时*/
QPushButton:pressed {
background-color:rgba(100,255,100,200);
border-color:rgba(255, 225,255,30);
border-style:inset;
color:rgba(0, 0, 0, 100);
}
/************滑块部件*****************/
/*水平滑块的手柄*/
QSlider::handle:horizontal{
image:url(:/image/sliderHandle.png);
}
/*水平滑块手柄以前的部分*/
QSlider::sub-page:horizontal {
/*边框图片*/
border-image: url(:/image/slider.png);
}
下面回到设计模式,将界面上的pushButton部件大小更改为宽120、高40,将horizontalSlider部件的大小更改为宽280、高6。现在运行程序,拖动滑块手柄,然后按下按钮,效果如图所示。
在myresource.qrc文件上右击,在弹出的级联菜单中选择OpeninEditor,打开资源文件。然后选择添加前缀,再添加一个“/qss”"前缀(添加这个前缀只是为了将文件区分开),再选择添加文件,选择项目目录下新添加的my. qss和my1.qss文件。最后按下Ctrl+S保存修改。
这二个文件就是样式表的保存,用来换肤用的
//my.qss
/****************主界面背景*******************/
QMainWindow{
/*背景图片*/
background-image: url(:/image/beijing01.png);
}
/****************按钮部件*******************/
QPushButton{
/*背景色*/
background-color: rgba(100, 225, 100, 30);
/*边框样式*/
border-style: outset;
/*边框宽度为4像素*/
border-width: 4px;
/*边框圆角半径*/
border-radius: 10px;
/*边框颜色*/
border-color: rgba(255, 225, 255, 30);
/*字体*/
font: bold 14px;
/*字体颜色*/
color:rgba(0, 0, 0, 100);
/*填衬*/
padding: 6px;
}
/*鼠标悬停在按钮上时*/
QPushButton:hover{
background-color:rgba(100,255,100, 100);
border-color: rgba(255, 225, 255, 200);
color:rgba(0, 0, 0, 200);
}
/*按钮被按下时*/
QPushButton:pressed {
background-color:rgba(100,255,100, 200);
border-color: rgba(255, 225, 255, 30);
border-style: inset;
color:rgba(0, 0, 0, 100);
}
/****************滑块部件*******************/
/*水平滑块的手柄*/
QSlider::handle:horizontal {
image: url(:/image/sliderHandle.png);
}
/*水平滑块手柄以前的部分*/
QSlider::sub-page:horizontal {
/*边框图片*/
border-image: url(:/image/slider.png);
}
第二个
//my1.qss
/****************主界面背景*******************/
QMainWindow{
/*背景图片*/
background-image: url(:/image/beijing02.png);
}
/****************按钮部件*******************/
QPushButton{
/*背景色*/
background-color: rgba(100, 100, 100, 30);
/*边框样式*/
border-style: outset;
/*边框宽度为4像素*/
border-width: 4px;
/*边框圆角半径*/
border-radius: 10px;
/*边框颜色*/
border-color: rgba(255, 120, 120, 30);
/*字体*/
font: bold 14px;
/*字体颜色*/
color:rgba(0, 100, 0, 100);
/*填衬*/
padding: 6px;
}
/*鼠标悬停在按钮上时*/
QPushButton:hover{
background-color:rgba(200,255,100, 100);
border-color: rgba(255, 225, 255, 200);
color:rgba(0, 0, 0, 200);
}
/*按钮被按下时*/
QPushButton:pressed {
background-color:rgba(255,255,255, 200);
border-color: rgba(255, 225, 255, 30);
border-style: inset;
color:rgba(0, 0, 0, 100);
}
/****************滑块部件*******************/
/*水平滑块的手柄*/
QSlider::handle:horizontal {
image: url(:/image/sliderHandle.png);
}
/*水平滑块手柄以前的部分*/
QSlider::sub-page:horizontal {
/*边框图片*/
border-image: url(:/image/slider.png);
}
下面打开mainwindow.h添加前置声明
class QFile;
然后添加一个私有对象
QFile *qssFile;
转到mainWindow.cpp文件中添加头文件#include< QFile>,然后在构造函数中添加代码:
qssFile = new QFile(":/qss/my.qss", this);
// 只读方式打开该文件
qssFile->open(QFile::ReadOnly);
// 读取文件全部内容,使用tr()函数将其转换为QString类型
QString styleSheet = tr(qssFile->readAll());
// 为QApplication设置样式表
qApp->setStyleSheet(styleSheet);
qssFile->close();
这里读取了Qt样式表文件中的内容,然后为应用程序设置了样式表。下面再进入设计模式,将pushButton的文本更改为“换肤”,然后转到它的单击信号对应的槽中,更改如下:
void MainWindow::on_pushButton_clicked()
{
if(qssFile->fileName() == ":/qss/my.qss")
qssFile->setFileName(":/qss/my1.qss");
else qssFile->setFileName(":/qss/my.qss");
qssFile->open(QFile::ReadOnly);
QString styleSheet = tr(qssFile->readAll());
qApp->setStyleSheet(styleSheet);
qssFile->close();
}
现在运行程序,按下按钮后便会更改界面的外观,这样就实现了换肤功能。
这个程序是将. qss文件放到了资源文件中,其实它也可以放在程序外,可以使用任意的文本编辑器进行编写,只要最后以. qss为后缀保存即可。
如果放在了程序外,那么就要更改程序中的文件路径,还要注意更改样式表中使用的图片路径。
样式表的内容就讲到这里,可以在帮助中通过Qt Style Sheets
关键字来查看更多相关内容的学习。Qt Style Sheets Examples
关键字对应的文档中列举了很多常用部件的一些样式表应用范例,可以作为参考。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)