目录
(一)背景介绍
(二)基本语法
(三)QSS设置方式
3.1 指定控件样式设置
3.2 全局样式设置
3.3 使用Qt Designer编辑样式
(四)选择器
4.1 选择器概况
4.2 子控件选择器(Sub-Controls)
4.3 伪类选择器(Pseudo-States)
(五)样式属性
5.1 盒模型(BoxModel)
(六)控件样式示例
6.1 按钮
6.2 复选框
总结
(一)背景介绍
在网页前端开发领域中,CSS是⼀个至关重要的部分.描述了⼀个网页的"样式".从起到对网页美化的 作用。
- 所谓样式,包括不限于大小,位置,颜色,背景,间距,字体等等.
- 现在的网页很难找到没有CSS的.可以说让"界面好看"是⼀个刚需.
"好看"这个事情有没有意义呢?是否⼀个软件,能满足核心功能即可,界面好看无所谓呢? 参考知乎上的这个帖子:https://www.zhihu.com/question/30918916/answer/49934463
- 网页开发作为GUI的典型代表,也对于其他客户端GUI开发产⽣了影响.Qt也是其中之⼀.
Qt 仿照CSS的模式,引入了QSS,来对Qt中的控件做出样式上的设定,从而允许程序猿写出界面更好看的代码.
- 同样受到HTML的影响,Qt还引⼊了QML来描述界面,甚至还可以直接把⼀个原生的html页面加载到界面上.这部分内容这里不做讨论.
当然,由于Qt本身的设计理念和网页前端还是存在⼀定差异的,因此QSS中只能支持部分CSS属性. 整体来说QSS要比CSS更简单⼀些.
注意: 如果通过QSS设置的样式和通过C++代码设置的样式冲突,则QSS优先级更⾼
(二)基本语法
对于CSS来说,基本的语法结构非常简单.
选择器
{
属性名: 属性值;
}
QSS沿用户了这样的设定.
选择器
{
属性名: 属性值;
}
其中:
- 选择器描述了"哪个widget要应用样式规则".
- 属性则是⼀个键值对,属性名表示要设置哪种样式,属性值表示了设置的样式的值.
例如:
QPushButton { color: red; }
或者
QPushButton {
color: red;
}
- 上述代码的含义表示,针对界面上所有的QPushButton,都把文本颜色设置为 “红色”
代码示例:
1) 在界面上创建⼀个按钮.
2) 编写代码,设置样式
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->pushButton->setStyleSheet("QPushButton { color: red; }");
}
3) 运行程序,观察效果.可以看到文本已经是红色了.
- 上述代码中,我们是只针对这⼀个按钮通过 setStyleSheet 方法设置的样式.此时这个样式 仅针对该按钮生效.如果创建其他按钮,其他按钮不会受到影响.
(三)QSS设置方式
3.1 指定控件样式设置
QWidget 中包含了 setStyleSheet 方法,可以直接设置样式. 上述代码我们已经演示了上述设置方式.
另⼀方面,给指定控件设置样式之后,该控件的子元素也会受到影响.
代码示例:
1) 在界面上创建⼀个按钮
2) 修改widget.cpp,这次我们不再给按钮设置样式,而是给Widget设置样式(Widget是 QPushButton的父控件).
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 给Widget 本⾝设置样式
this->setStyleSheet("QPushButton { color: red;} ");
}
3) 运行程序,可以看到样式对于子控件按钮同样会生效.
3.2 全局样式设置
还可以通过 QApplication 的 setStyleSheet 方法设置整个程序的全局样式.
全局样式优点:
- 使同⼀个样式针对多个控件生效,代码更简洁.
- 所有控件样式内聚在⼀起,便于维护和问题排查.
代码示例:
1) 在界面上创建三个按钮.
2) 编辑main.cpp,设置全局样式
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//设置全局样式
a.setStyleSheet("QPushButton { color: red; }");
Widget w;
w.show();
return a.exec();
}
3) 运行程序,可以看到此时三个按钮的颜色都设置为红色了.
代码示例:样式的层叠特性
如果通过全局样式给某个控件设置了属性1,通过指定控件样式给控件设置属性2,那么这两个属性都会产生作用.
1) 在界面上创建两个按钮
2) 编写main.cpp,设置全局样式,把按钮文本设置为红色.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 设置全局样式
a.setStyleSheet("QPushButton { color: red; }");
Widget w;
w.show();
return a.exec();
}
3) 编写widget.cpp,给第⼀个按钮设置字体大小
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//设置指定控件样式
ui->pushButton->setStyleSheet("QPushButton { font-size: 50px} ");
}
4) 运行程序,可以看到,对于第⼀个按钮来说,同时具备了颜色和字体大小样式.而第⼆个按钮只有颜色样式.
- 说明针对第⼀个按钮,两种设置方式设置的样式,叠加起来了.
- 形如上述这种属性叠加的效果,我们称为"层叠性".
- CSS全称为CascadingStyleSheets,其中Cascading就是"层叠性"的意思QSS也继承了这 样的设定.
- 实际上把QSS叫做QCSS也许更合适⼀些~
3.3 使用Qt Designer编辑样式
QSS也可以通过QtDesigner直接编辑,从而起到实时预览的效果.同时也能避免C++和QSS代码的耦合.
代码示例:使用Qt Designer编辑样式
1) 在界面上创建⼀个按钮
2) 右键按钮,选择"改变样式表"
3) 在弹出的样式表编辑器中,可以直接填写样式.填写完毕,点击OK即可.
4) 此时QtDesigner的预览界面就会实时显示出样式的变化.
5) 运行程序,可以看到样式确实发生了改变.
这种方式设置样式,样式内容会被以xml格式记录到ui文件中.
<property name="styleSheet">
<string notr="true">QPushButton { color: red; }</string>
</property>
同时在控件的 styleSheet 属性中也会体现.
当我们发现⼀个控件的样式不符合预期的时候,要记得排查这四个地方:
- 全局样式
- 指定控件样式
- qss文件中的样式
- ui文件中的样式
(四)选择器
4.1 选择器概况
QSS的选择器支持以下几种:
- 总体来说,QSS选择器的规则和CSS选择器基本⼀致.
- 上述选择器咱们也不需要全都掌握,就只熟悉最常用的几个即可(上述加粗的).
代码示例:使用类型选择器选中子类控件
1) 在界面上创建⼀个按钮.
2) 修改main.cpp,设置全局样式
- 注意,此处选择器使用的是QWidget . QPushButton也是QWidget 的子类,所以会到, QWidget 选择器的影响
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//设置全局样式
a.setStyleSheet("QWidget { color: red; }");
Widget w;
w.show();
return a.exec();
}
3) 运行程序,可以看到按钮的文本颜色已经是红色了.
5) 如果把上述样式代码修改为下列代码
a.setStyleSheet(".QWidget { color: red; }");
- 此时按钮的颜⾊不会发生改变.此时只是选择 QWidget 了. 而不会选择 QWidget 的子类QPushButton
4.2 子控件选择器(Sub-Controls)
有些控件内部包含了多个"子控件".比如QComboBox的下拉后的面板,比如QSpinBox的上下按钮等.
可以通过子控件选择器 :: ,针对上述子控件进行样式设置.
代码示例:设置下拉框的下拉按钮样式
1) 在界面上创建⼀个下拉框,并创建几个选项
2) 创建 resource.qrc ,并导入图片 down.png
3) 修改main.cpp,编写全局样式
- 使用子控件选择器 QComboBox::down-arrow 选中了
- 再通过 image 属性设置图片.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString style = "";
style += "QComboBox::down-arrow { image: url(:/down.png) }";
a.setStyleSheet(style);
Widget w;
w.show();
return a.exec();
}
4) 执行程序,观察效果
4.3 伪类选择器(Pseudo-States)
伪类选择器,是根据控件所处的某个状态被选择的.例如按钮被按下,输入框获取到焦点,⿏标移动到某 个控件上等.
- 当状态具备时,控件被选中,样式生效.
- 当状态不具备时,控件不被选中,样式失效.
使用 : 的方式定义伪类选择器.
常用的伪类选择器
这些状态可以使用 !来取反.比如 :!hover 就是⿏标离开控件时, :!pressed 就是⿏标松开时,等等.
(五)样式属性
QSS中的样式属性非常多,不需要都记住.核心原则还是用到了直接去查. 大部分的属性和CSS是非常相似的。(文档的 Qt Style Sheets Reference 章节详细介绍了哪些控件可以设置属性,每个控件都能设置哪些属性等.)
5.1 盒模型(BoxModel)
在文档的Customizing Qt Widgets Using Style Sheets 的 The Box Model 章节介绍了盒模型.
⼀个遵守盒模型的控件,由上述几个部分构成.
- Content 矩形区域:存放控件内容.比如包含的文本/图标等.
- Border 矩形区域:控件的边框.
- Padding 矩形区域:内边距.边框和内容之间的距离.
- Margin 矩形区域:外边距.边框到控件
默认情况下,外边距,内边距,边框宽度都是0.
可以通过⼀些QSS属性来设置上述的边距和边框的样式.
代码示例:设置边框和内边距
1) 在界面上创建⼀个label
2) 修改main.cpp,设置全局样式
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setStyleSheet("QLabel { border: 5px solid red; padding-left: 10px; }");
Widget w;
w.show();
return a.exec();
}
3) 运行程序,可以看到样式发生了变化
(六)控件样式示例
下⾯给出⼀些常⽤控件的样式示例.
6.1 按钮
代码示例:自定义按钮
1) 界面上创建⼀个按钮
2) 右键->改变样式表,使用QtDesigner设置样式
QPushButton {
font-size: 20px;
border: 2px solid #8f8f91;
border-radius: 15px;
background-color: #dadbde;
}
QPushButton:pressed {
background-color: #f6f7fa;
}
3) 执行程序,可以看到效果
代码示例:设置外边距
为了方便确定控件位置,演示外边距效果,我们使用代码创建⼀个按钮.
1) 修改widget.cpp,创建按钮,并设置样式.
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* btn = new QPushButton(this);
btn->setGeometry(0, 0, 100, 100);
btn->setText("hello");
btn->setStyleSheet("QPushButton { border: 5px solid red; margin: 20px; }");
const QRect& rect = btn->geometry();
qDebug() << rect;
}
2) 运行程序,可以看到,当前按钮的边框被外边距挤的缩小了.但是获取到的按钮的的. Geometry 是不变
6.2 复选框
代码示例:自定义复选框
1) 创建⼀个 resource.qrc 文件,并导入以下图片.
使用黑色作为默认形态. 使用黑色作为hover形态. 使用红色作为pressed形态.
2) 创建⼀个复选框
3) 编辑复选框的样式
QCheckBox {
font-size: 20px;
}
QCheckBox::indicator {
width: 20px;
height: 20px;
}
QCheckBox::indicator:unchecked {
image: url(:/checkbox-unchecked.png);
}
QCheckBox::indicator:unchecked:hover {
image: url(:/checkbox-unchecked_hover.png);
}
QCheckBox::indicator:unchecked:pressed {
image: url(:/checkbox-unchecked_pressed.png);
}
QCheckBox::indicator:checked {
image: url(:/checkbox-checked.png);
}
QCheckBox::indicator:checked:hover {
image: url(:/checkbox-checked_hover.png);
}
QCheckBox::indicator:checked:pressed {
image: url(:/checkbox-checked_pressed.png);
}
4) 运行程序,可以看到此时的复选框就变的丰富起来了.
除了上述之外,还有包括像单选框、列表、输入框等各种控件,在这里就不一一演示了!!
总结
QSS本身给Qt提供了更丰富的样式设置的能力,但是整体来说QSS的功能是不如CSS的.
在CSS中,整个网页的样式,都是CSS一手负责,CSS功能更强大,并且也更可控.
相⽐之下,Qt中是以原生api为主,来控制控件之间的尺寸,位置等,QSS只是起到辅助的作用.
而且Qt中提供的⼀些"组合控件"(像QComboBox,QSpinBox等)内部的结构是不透明的,此时进行⼀ 些样式设置也会存在⼀定的局限性.
另外,做出好看的界面,光靠QSS是不够的.更重要的是需要专业美工做出设计稿.这里主要是了解这个技术