Qt 项目中使用 QSS 的全面总结

一、什么是 QSS?

QSS(Qt Style Sheets) 是 Qt 框架提供的一种样式表机制,用于自定义控件的外观。它的语法大量参考了 Web 开发中的 CSS,但功能相对较弱:可用的选择器类型更少,支持的样式属性也有限,并且并非所有属性都能应用于任意控件。

不过,QSS 已经足以帮助我们实现大多数常见的界面美化需求,例如设置背景色、字体、边框、圆角、悬停效果等。


二、QSS 的使用方法

2.1 基本步骤

  1. 编写 QSS 样式文本(通常保存在 .qss 文件中)。

  2. 在程序中读取该文件内容。

  3. 调用控件的 setStyleSheet() 方法应用样式。

2.2 代码示例

cpp 复制代码
MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent),
      ui(new Ui::MainWidget)
{
    // 加载 qss 文件
    QFile file(":/qss/main.qss");
    file.open(QFile::ReadOnly);
    QTextStream filetext(&file);
    QString stylesheet = filetext.readAll();
    file.close();

    // 应用到当前窗口及其所有子控件
    this->setStyleSheet(stylesheet);
}

注意setStyleSheet()QWidget 的成员函数,因此几乎任何控件都可以单独设置自己的样式表。

三、QSS 语法规则

QSS 的语法规则与 CSS 基本一致,由 选择器声明块 组成:

复制代码
选择器 { 属性: 值; 属性: 值; ... }

示例

复制代码
QPushButton { color: red; }

这条规则的意思是:将所有 QPushButton 及其子类的文字颜色设置为红色。

与 CSS 的不同之处

在 CSS 中,选择器 div 只匹配 <div> 标签;而在 QSS 中,类型选择器 QPushButton 不仅匹配 QPushButton 本身,还匹配所有继承自 QPushButton 的子类(例如 MyButton)。

如果只想匹配确切的 QPushButton 类(不包括子类),可以使用 类选择器(前面加一个点):

复制代码
.QPushButton { color: red; }   // 只匹配 QPushButton,不匹配子类

四、QSS 选择器类型

选择器类型 语法示例 说明
通配选择器 * 匹配所有控件
类型选择器 QPushButton 匹配该类及其子类的所有实例
类选择器 .QPushButton 只匹配该类本身,不匹配子类
ID 选择器 #myButton 匹配 objectNamemyButton 的控件
属性选择器 QPushButton[flat="false"] 匹配 flat 属性为 false 的按钮(属性可以是自定义的)
后代选择器 QDialog QPushButton 匹配 QDialog任意层级QPushButton
子选择器 QDialog > QPushButton 匹配 QDialog 直接子容器 中的 QPushButton

组合使用

多个选择器可以组合,也可以使用逗号同时为多个选择器指定同一套规则:

cpp 复制代码
/* 组合后代选择器 */
#mytable QPushButton { background: gray; }

/* 多选择器共用规则 */
#frameCut, #frameInterrupt, #frameJoin { border: 1px solid black; }

五、子控件选择器

对于 复合控件 (如 QComboBoxQSpinBox 等),我们可以通过 子控件选择器 来定制其内部的某个部分。

子控件选择器使用双冒号 :: 表示,例如:

复制代码
QComboBox::drop-down { image: url(dropdown.png); }

这行代码将 QComboBox 的下拉按钮图片替换为自定义图片。

也可以与其他选择器结合:

复制代码
QComboBox#myQComboBox::drop-down { image: url(dropdown.png); }

常见子控件::drop-down(下拉按钮)、::down-arrow(向下箭头)、::up-button(上调节按钮)、::tab-bar(标签栏)等。具体列表可查阅 Qt 帮助文档。

六、伪状态选择器

伪状态选择器用于匹配控件在特定状态下的样式。它使用冒号 : 开头,且必须放在选择器的最后面

示例

cpp 复制代码
/* 鼠标悬停时背景变红 */
QComboBox:hover { background-color: red; }

/* 鼠标悬停在下拉箭头上时背景变红 */
QComboBox::drop-down:hover { background-color: red; }

伪状态的逻辑运算

  • 取反 :使用 !,例如 :!hover 表示非悬停状态。

  • 组合 :多个伪状态可以连写,如 :hover:checked

cpp 复制代码
QCheckBox:hover:checked { color: white; }

Qt 提供了大量伪状态,如 :checked(选中)、:disabled(禁用)、:focus(获得焦点)、:pressed(按下)等,具体可查阅官方文档。

七、级联与冲突

7.1 冲突解决:特异性(权重)

当多个规则同时作用于同一控件的同一属性时,QSS 根据 特异性(权重)来决定最终应用哪个规则。

权重计算规则(与 CSS 一致):

  1. 统计规则中 ID 选择器 的个数 → 记为 a

  2. 统计 类选择器、属性选择器、伪状态 的个数 → 记为 b

  3. 统计 类型选择器 (如 QPushButton)的个数 → 记为 c

最终权重为 a b c(按位比较)。权重值越大,优先级越高。

示例

cpp 复制代码
*               { color: black; }  /* a=0, b=0, c=0 → 权重  0 */
QPushButton     { color: red;   }  /* a=0, b=0, c=1 → 权重  1 */
QPushButton:hover { color: blue; } /* a=0, b=1, c=1 → 权重 11 */
#okButton       { color: green; }  /* a=1, b=0, c=0 → 权重100 */

因此,#okButton 的规则会覆盖前面所有规则。

如果两条规则权重相同,则后出现的规则生效。

7.2 继承与级联

  • 一个控件可以同时受到 父控件自身 上设置的样式影响,最终效果是合并所有适用的样式。

  • 如果发生冲突(同一属性在不同层级被设置),子控件自己的样式 优先级最高。

示例

cpp 复制代码
qApp->setStyleSheet("QPushButton { color: white; }");
myButton->setStyleSheet("* { color: blue; }");

最终 myButton 的文字颜色为蓝色(自身样式覆盖了全局样式)。

注意 :父控件设置的样式不会自动被子控件继承,除非该样式明确选择了子控件。例如:

cpp 复制代码
// 这个样式只影响 QFrame 本身,不会影响其内部的 QPushButton
ui->frame->setStyleSheet("QFrame { color: red; }");

// 这个样式会影响 frame 内所有的 QPushButton
ui->frame->setStyleSheet("QPushButton { color: red; }");

八、实际应用中的注意事项

8.1 边框设置的属性顺序

正确写法

cpp 复制代码
border: 1px solid red;   /* 宽度 样式 颜色 */

错误写法(顺序随意会导致无效):

cpp 复制代码
border: solid 1px red;   /* 无效 */
border: red 1px solid;   /* 无效 */
border: red solid 1px;   /* 无效 */

8.2 设置控件的宽高

在 QSS 中直接使用 widthheight 通常无效。正确的做法是使用:

  • min-width / min-height

  • max-width / max-height

cpp 复制代码
QPushButton {
    min-width: 80px;
    min-height: 30px;
    max-width: 120px;
}

8.3 QComboBox 的样式定制

QComboBox 是一个复杂的复合控件,需要分别定制其不同部分。

选择器 作用
QComboBox 组合框主体(未弹出下拉列表时)
QComboBox::drop-down 下拉按钮
QComboBox::down-arrow 下拉箭头图标
QComboBox QAbstractItemView 弹出的下拉列表的整个矩形区域
QComboBox QAbstractItemView::item 下拉列表中的每一个选项

示例

cpp 复制代码
/* 下拉列表整体样式 */
QComboBox QAbstractItemView {
    border: 1px solid gray;
    background: white;
}

/* 下拉列表项样式(需要先设置 item delegate 才能生效) */
QComboBox QAbstractItemView::item {
    height: 30px;
    padding: 5px;
}

注意 :要使 ::item 样式生效,必须为 QComboBox 设置 QStyledItemDelegate

cpp 复制代码
QStyledItemDelegate* delegate = new QStyledItemDelegate();
comboBox->setItemDelegate(delegate);

九、总结

本文系统介绍了 Qt 中 QSS 的核心知识:

  • 什么是 QSS:Qt 的样式表语言,类似 CSS。

  • 如何使用 :读取 .qss 文件并调用 setStyleSheet()

  • 选择器系统:类型、类、ID、属性、后代、子选择器,以及子控件和伪状态。

  • 级联与冲突:权重计算规则和优先级。

  • 常见坑点 :边框属性顺序、宽高设置、QComboBox 的特殊处理。

掌握这些内容后,你已经能够灵活运用 QSS 美化 Qt 应用程序的界面。如果需要更详细的信息,建议查阅 Qt 官方文档中关于 Qt Style Sheets 的章节。

相关推荐
用户805533698034 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner4 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz9 天前
QML Hello World 入门示例
qt
xcyxiner12 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner13 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner13 天前
DicomViewer (添加模型类)3
qt
xcyxiner14 天前
DicomViewer (目录调整) 2
qt
xcyxiner14 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00616 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术16 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript