目录
前言:
Qt中的样式设置是通过QSS设置的。QSS是设置和美化Qt界面的一种机制。Qt仿照前端技术CSS的模式,引入了 QSS 来对 Qt 中的控件做出样式上的设定。
1,QSS样式运用
1-1,setStyleSheet设置
选择器 {
属性名: 属性值;
}
选择器:选择要设置样式的控件类型或对象名。
属性:则是⼀个键值对。属性名表示要设置哪种样式,属性值表示了设置的样式的值。常用的属性有:font-size 设置字体大小、border-radius 设置圆角矩形、background-cokor 设置背景颜色、color 设置文字颜色、background-image 设置背景图片等。
样例:
QPushButton { color: red; }
QPushButton { background-image: url(:/images/button_bg.png); }
部件的样式设置是通过控件的 setStyleSheet 方法设置的。setStyleSheet 设置完后,该控件的子元素也会受到影响,但其它控件不会受到影响。
// 给 Widget 本⾝设置样式。运行程序,可以看到样式对于⼦控件按钮同样会⽣效.
this->setStyleSheet("QPushButton { color: red;} ");
QPushButton* button = new QPushButton(this);
注意:若是给 QApplication 使用 setStyleSheet 方法设置样式,那么整个程序下部件的样式都会发生变化,即设置全局样式。
如果全局样式和指定控件样式冲突,则指定控件样式优先展示,所以我们也可以设置单个控件的样式来改变。
1-2,从文件加载样式表
通常情况下,样式的设置是与代码分离的。我们可以把样式放到单独的文件中(后缀名为.qss的文件),然后通过读取文件的方式来加载样式。如下:
首先,创建 resource.qrc 文件,并设定前缀为/。
然后,创建 style.qss 文件,并添加到 resource.qrc 中。style.qss 是需要程序运行时加载的,为了规避绝对路径的问题,这里仍然使用 qrc 的方式来组织(即把资源文件内容打包到 cpp 代码中)。由于 Qt Creator 没有提供创建 qss 文件的选项,所以这里直接:右键 -> 新建文件 -> 手动设置文件扩展名为 qss -> 添加。
接下来就是使用 Qt Creator 打开 style.qss 编写内容。如下图:
下面就是使用 style.qss 文件。通常是先读取文件的全部内容,然后使用 setStyleSheet 方法将其设置给 QApplication 主程序变量。如下:
QString loadQSS() {
QFile file(":/style.qss");
// 打开⽂件
file.open(QFile::ReadOnly);
// 读取⽂件内容. 虽然 readAll 返回的是 QByteArray, 但是 QString 提供了 QByteArray 的构造函数
QString style = file.readAll();
// 关闭⽂件
file.close();
return style;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 调⽤上述函数加载样式
a.setStyleSheet(loadQSS());
Widget w;
w.show();
return a.exec();
}
1-3,Qt Designer编辑样式
QSS 也可以通过 Qt Designer 直接编辑。如下:
在弹出的样式表编辑器中,可以直接填写样式;填写完毕后点击 OK 即可。
然而,这种方式设置的样式内容会被以 xml 格式记录到 ui 文件中。
2,选择器
2-1,选择器的类型
QSS的选择器支持以下几种:
上述选择器不需要全都掌握,只需熟悉上述加粗的即可。
// 该控件下的子控件全部生效
a.setStyleSheet("QWidget { color: red; }");
// 该控件下的子空间不会生效
a.setStyleSheet(".QWidget { color: red; }");
// objectName为button的控件生效
QPushButton* button = new QPushButton(this);
a.setStyleSheet("#button { color: red; }");
// QPushButton, QLabel, QLineEdit三种控件以及子控件生效
a.setStyleSheet("QPushButton, QLabel, QLineEdit { color: red; } ");
2-2,子控件选择器
有些控件内部包含了多个 “子控件”,比如 QComboBox 的下拉后的面板,比如 QSpinBox 的上下按钮等。这里可以通过子控件选择器 :: 针对上述子控件进行样式设置。
// 使⽤⼦控件选择器 QComboBox::down-arrow,设置 QComboBox 下拉按钮图片
// down-arrow 代表下拉按钮
QComboBox* box = new QComboBox(this);
box->setStyleSheet("QComboBox::down-arrow { image: url(:/a.jpg)}");
// 设置进度条"加载块"的颜色为红色
// chunk 是选中进度条中的每个"块",使⽤ QProgressBar::text 则可以选中⽂本
QProgressBar::chunk {background-color: #FF0000;}
常用的子控件还有 QScrollBar::add-line、QTabBar::tab、QSlider::handle。
最后说明下,Qt控件下的子控件多种做样,用到时自行查看即可,这里没必要死记。
2-3,伪类选择器
伪类选择器是根据控件所处的某个状态被选择的,例如按钮被按下、输入框获取到焦点、鼠标移动到某个控件上等。只有当状态具备时,控件被选中,样式才生效。伪类选择器使用 : 的方式定义。
这些状态可以使用 ! 来取反,比如 :!hover 就是鼠标离开控件时,:!pressed 就是鼠标松开时等等。代码示例如下:设置按钮的伪类样式。
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString style = "";
style += "QPushButton { color: red; }";
style += "QPushButton:hover { color: green; }";
style += "QPushButton:pressed { color: blue; }";
a.setStyleSheet(style);
Widget w;
w.show();
return a.exec();
}
3,盒模型
在Qt中,盒模型主要用来描述控件的布局和尺寸计算方式。⼀个遵守盒模型的控件由下面几个部分构成。
- Content矩形区域:存放控件内容,比如包含的⽂本/图标等。
- Border矩形区域:控件的边框。
- Padding矩形区域: 内边距,边框和内容之间的距离。
- Margin矩形区域:外边距,边框到控件 geometry 返回的矩形边界的距离。
默认情况下,外边距,内边距,边框宽度都是0。可以通过⼀些 QSS 属性来设置上述的边距和边框的样式。
上面 margin 属性又可以拆分四个属性:margin-left、margin-right、margin-top、margin-bottom。padding 也是可以拆分四个属性:padding-left、padding-right、padding-top、padding-bottom。
下面来设置 label 标签的边框和内边距。
// border: 5px solid red 相当于 border-style: solid; border-width: 5px; border-color: red;三个属性的简写形式
// padding-left: 10px; 是给左侧设置内边距
QApplication a(argc, argv);
a.setStyleSheet("QLabel { border: 5px solid red; padding-left: 10px; }");
下面来设置按钮控件的外边距。
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;
4,控件样式的综合设置
下面来代码实验给控件设置样式。
4-1,复选框
// 下面相关的子控件自行查看,这里不做说明
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-2,单选框
QWidget QRadioButton {
font-size: 20px;
}
QWidget QRadioButton::indicator {
width: 20px;
height: 20px;
}
QWidget QRadioButton::indicator:unchecked {
image: url(:/radio-unchecked.png);
}
QWidget QRadioButton::indicator:unchecked:hover {
image: url(:/radio-unchecked_hover.png);
}
QWidget QRadioButton::indicator:unchecked:pressed {
image: url(:/radio-unchecked_pressed.png);
}
QWidget QRadioButton::indicator:checked {
image: url(:/radio-checked.png);
}
QWidget QRadioButton::indicator:checked:hover {
image: url(:/radio-checked_hover.png);
}
QWidget QRadioButton::indicator:checked:pressed {
image: url(:/radio-checked_pressed.png);
}
4-3,输入框
QLineEdit {
border-width: 1px;
border-radius: 10px;
border-color: rgb(58, 58, 58);
border-style: inset;
padding: 0 8px;
color: rgb(255, 255, 255);
background:rgb(100, 100, 100);
selection-background-color: rgb(187, 187, 187);
selection-color: rgb(60, 63, 65);
}
4-4,列表
QListView::item:hover {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #FAFBFE, stop: 1 #DCDEF1);
}
QListView::item:selected {
border: 1px solid #6a6ea9;
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #6a6ea9, stop: 1 #888dd9);
}
这里说明下渐变色。qlineargradient 有6个参数,x1,y1:标注了⼀个起点;x2,y2:标注了⼀个终点。这两个点描述了一个 "方向"。例如:x1:0, y1:0, x2:0, y2:1 就是垂直⽅向从上向下进⾏颜⾊渐变、x1:0,y1:0,x2:1,y2:0 就是⽔平⽅向从左向右进⾏颜⾊渐变、x1:0,y1:0,x2:1,y2:1 就是从左上往右下⽅向进⾏颜⾊渐变。
4-5,菜单栏
QMenuBar {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 lightgray, stop:1 darkgray);
spacing: 3px;
}
QMenuBar::item {
padding: 1px 4px;
background: transparent;
border-radius: 4px;
}
QMenuBar::item:selected {
background: #a8a8a8;
}
QMenuBar::item:pressed {
background: #888888;
}
QMenu {
background-color: white;
margin: 0 2px;
}
QMenu::item {
padding: 2px 25px 2px 20px;
border: 3px solid transparent;
}
QMenu::item:selected {
border-color: darkblue;
background: rgba(100, 100, 100, 150);
}
QMenu::separator {
height: 2px;
background: lightblue;
margin-left: 10px;
margin-right: 5px;
}