QSS(Quick Style Sheet)是一种用于定义Qt应用程序样式的机制。Qt是一个跨平台的C++应用程序开发框架,而QSS则允许开发者使用类似于CSS(层叠样式表)的语法来定义Qt应用程序的外观和风格。
一、QSS的基本语法
QSS的语法类似于CSS,通过设置属性和值的方式定义样式。例如:
QPushButton {
background-color: lightblue;
border: 2px solid darkblue;
color: white;
}
这个例子定义了一个QPushButton(按钮)的样式,设置了背景颜色、边框和文本颜色。
二、选择器类型
-
基础选择器
- 类型选择器:通过控件类型匹配,如
QLineEdit
匹配所有输入框。 - ID 选择器:通过
objectName
匹配,如QPushButton#loginBtn
定位名为loginBtn
的按钮。 - 类选择器:通过自定义类名匹配,如
.MyButton
。
- 类型选择器:通过控件类型匹配,如
-
状态选择器
伪态用于根据控件的当前状态应用不同的样式。常见的伪态包括:
:hover
:鼠标悬停在控件上时。
:pressed
:控件被按下时。
:checked
:对于可检查的控件(如复选框和单选按钮),当它们被选中时。
:disabled
:控件被禁用时。
:focus
:控件获得焦点时。QPushButton:hover { /* 鼠标悬停 */ } QLineEdit:focus { /* 输入框聚焦 */ }
-
子控件选择器
定制复杂控件的子部件,例如:QTabBar::tab { /* 标签页的标签部分 */ } QScrollBar::handle { /* 滚动条滑块 */ }
三、QSS 应用
1.文件加载
在资源文件中,将QSS样式文件添加到Qt资源文件(.qrc)中,然后通过资源路径加载。
QFile file(":/style.qss");
file.open(QFile::ReadOnly);
qApp->setStyleSheet(file.readAll());
2.代码内联设置
直接通过 setStyleSheet()
方法设置局部样式:
ui->pushButton->setStyleSheet("background: #53c23c;");
3.全局样式
如果你想改变整个应用程序中所有小部件的样式,可以直接对 QApplication
实例调用 setStyleSheet()
。例如,改变所有窗口的背景颜色:
app.setStyleSheet("QWidget { background-color: lightgray; }");
4.针对特定对象设置样式
你也可以为特定的对象设置样式,只需要指定对象的类名或对象名。例如,只改变一个按钮的样式:
app.setStyleSheet("MyButton { background-color: red; color: yellow; }");
然后在你的代码中给按钮设置一个对象名:
QPushButton button("Click Me");
button.setObjectName("MyButton");
button.show();
5.组合使用类选择器和对象名选择器
你可以组合使用类选择器和对象名选择器来精确控制样式:
app.setStyleSheet("QPushButton#MyButton { background-color: red; color: yellow; }");
6.使用动态样式表
如果你需要在运行时根据某些条件改变样式,你可以在C++代码中动态地更新样式表。
// C++代码
QString styleSheet = "QPushButton { background-color: %1; }";
if (someCondition) {
styleSheet = styleSheet.arg("#FF0000"); // 红色背景
} else {
styleSheet = styleSheet.arg("#00FF00"); // 绿色背景
}
button->setStyleSheet(styleSheet);
四、高级应用技巧
-
动态属性
QT中属性是指窗口或控件的属性,比如opacity属性表示“透明度”,geometry指的是“位置和大小”,pos属性代表“位置”。qt中的控件有自带的属性,我们也可以自己定义属性。QObject这个类有一个函数setProperty,我们可以通过这个函数定义自己的属性。结合动态属性和样式刷新实现状态切换。
如果为QObject设置一个urgent属性为true,该属性将跟随该类,但不会为urgent属性包含一个Q_PROPERTY宏。创建样式选择器依赖于动态属性,例如:urgent,可以用一个非常动态的方式凸显用户界面。例如:QLineEdit[urgent=true] { color: red; }
使用这种方式有局限性。最主要的是当一个属性值变化时,所引用的样式不会自动更新。相反地,必须手动触发更新才会生效。
unpolish()用于清理之前的样式,而polish()则用于添加新的样式。lineEdit->setProperty("urgent", true); lineEdit->style()->unpolish(lineEdit); lineEdit->style()->polish(lineEdit);
必须在组件的样式中使用,QStyle::polish既接受QWidge也接受QApplication作为参数。
-
盒模型与布局
通过padding
、margin
等属性调整控件内外边距,优化布局效果。QPushButton { padding: 10px; /* 内边距 */ margin: 5px; /* 外边距 */ }
QPushButton { padding: 10px 20px 15px 5px; /* 上 10px, 右 20px, 下 15px, 左 5px */ }
QLabel { margin: 10px 20px 15px 5px; /* 上 10px, 右 20px, 下 15px, 左 5px */ }
-
自定义控件样式
使用子控件选择器定制复杂控件(如QTabWidget
):QTabWidget::pane { border: 1px solid #C2C7CB; } QTabBar::tab { background: qlineargradient(...); }
4.全局样式与控件内局部样式的生效规则
1)样式叠加机制
当全局样式和控件内局部样式不冲突时,两者会叠加生效。例如:
-
全局样式设置
color: blue;
-
控件内样式设置
background-color: white;
此时控件的文字颜色和背景颜色均会生效。
2)冲突时的优先级
当全局样式与控件内局部样式属性冲突时,控件内局部样式具有更高优先级。例如:
-
全局样式设置
color: blue;
-
控件内样式设置
color: red;
此时控件文字颜色显示为红色。
3)强制继承父控件样式
- 使用
setAttribute(Qt::WA_StyledBackground, true)
使子控件继承父控件背景样式。
4)样式继承
子控件默认继承父控件样式。当 Qt 控件的默认样式无法通过常规规则修改时,可使用 !important
强制生效。
全局样式:
QPushButton { color: blue; }
局部样式:
QPushButton { color: red !important; }
此时按钮文字颜色会显示为红色,而非蓝色。
5.选择器优先级问题
1)优先级规则
- 陷阱:QSS 中类选择器(如
.MyWidget
)优先级高于 ID 选择器(如#myButton
),与 CSS 规则相反。 - 解决方案:使用更具体的选择器或
!important
强制覆盖,例如:QPushButton#loginBtn { color: red !important; }
2)多控件共用样式失效
- 原因:逗号分隔的选择器需重复声明父级路径。
- 示例:
/* 错误写法 */ EditInfo QPushButton#btnCancel, #btnConfirm { ... } /* 正确写法 */ EditInfo QPushButton#btnCancel, EditInfo QPushButton#btnConfirm { ... }
6.属性书写规范
-
属性名大小写
- QSS 属性名不区分大小写(如
color
与Color
等效),但建议保持统一写法。
- QSS 属性名不区分大小写(如
-
属性值引号与转义
- 含特殊字符的属性值需用引号包裹,例如:
QPushButton { text: "Click \"OK\""; } // 转义引号
- 含特殊字符的属性值需用引号包裹,例如: