【从零开始的Qt开发指南】(二十三)Qt 界面优化之 QSS 实战指南:从入门到精通,让你的界面颜值飙升!

目录

前言

[一、QSS 背景介绍:Qt 中的 "CSS",界面美化的刚需](#一、QSS 背景介绍:Qt 中的 “CSS”,界面美化的刚需)

[1.1 为什么需要 QSS?](#1.1 为什么需要 QSS?)

[1.2 QSS 与 CSS 的异同](#1.2 QSS 与 CSS 的异同)

[二、QSS 基本语法:简单直观,上手即会](#二、QSS 基本语法:简单直观,上手即会)

[2.1 核心语法结构](#2.1 核心语法结构)

[2.2 语法示例](#2.2 语法示例)

单行写法

多行写法

[2.3 最简单的 QSS 使用示例](#2.3 最简单的 QSS 使用示例)

[步骤 1:创建 Qt 项目并添加按钮控件](#步骤 1:创建 Qt 项目并添加按钮控件)

[步骤 2:在 C++ 代码中设置 QSS 样式](#步骤 2:在 C++ 代码中设置 QSS 样式)

[步骤 3:运行效果](#步骤 3:运行效果)

[三、QSS 设置方式:灵活多样,按需选择](#三、QSS 设置方式:灵活多样,按需选择)

[3.1 指定控件样式设置](#3.1 指定控件样式设置)

[3.1.1 单个控件样式设置](#3.1.1 单个控件样式设置)

[3.1.2 父控件样式设置(子元素继承)](#3.1.2 父控件样式设置(子元素继承))

代码示例

运行效果

[3.2 全局样式设置](#3.2 全局样式设置)

[3.2.1 全局样式的优点](#3.2.1 全局样式的优点)

[3.2.2 代码示例](#3.2.2 代码示例)

运行效果

[3.2.3 QSS 的层叠特性](#3.2.3 QSS 的层叠特性)

代码示例

运行效果

[3.3 从文件加载样式表(推荐)](#3.3 从文件加载样式表(推荐))

[3.3.1 实现步骤](#3.3.1 实现步骤)

[步骤 1:创建.qss 文件](#步骤 1:创建.qss 文件)

[步骤 2:编写 QSS 样式](#步骤 2:编写 QSS 样式)

[步骤 3:创建资源文件(.qrc)](#步骤 3:创建资源文件(.qrc))

[步骤 4:在 C++ 代码中加载.qss 文件](#步骤 4:在 C++ 代码中加载.qss 文件)

[3.3.2 运行效果](#3.3.2 运行效果)

[3.4 使用 Qt Designer 编辑样式(可视化操作)](#3.4 使用 Qt Designer 编辑样式(可视化操作))

[3.4.1 操作步骤](#3.4.1 操作步骤)

[步骤 1:在 Qt Designer 中选择控件](#步骤 1:在 Qt Designer 中选择控件)

[步骤 2:编辑样式表](#步骤 2:编辑样式表)

[步骤 3:保存样式](#步骤 3:保存样式)

[步骤 4:运行程序](#步骤 4:运行程序)

[3.4.2 特点](#3.4.2 特点)

[3.4.3 注意事项](#3.4.3 注意事项)

[四、QSS 选择器:精准定位,灵活匹配](#四、QSS 选择器:精准定位,灵活匹配)

[4.1 常用选择器概览](#4.1 常用选择器概览)

[4.2 各选择器详细用法与示例](#4.2 各选择器详细用法与示例)

[4.2.1 全局选择器(*)](#4.2.1 全局选择器(*))

示例

[4.2.2 类型选择器(Type Selector)](#4.2.2 类型选择器(Type Selector))

[示例 1:设置所有 QPushButton 及其子类的文本颜色为红色](#示例 1:设置所有 QPushButton 及其子类的文本颜色为红色)

[示例 2:通过父类选择器匹配子类控件](#示例 2:通过父类选择器匹配子类控件)

[4.2.3 类选择器(Class Selector)](#4.2.3 类选择器(Class Selector))

示例:类选择器与类型选择器的对比

[4.2.4 ID 选择器(ID Selector)](#4.2.4 ID 选择器(ID Selector))

[示例:通过 ID 选择器设置指定按钮的样式](#示例:通过 ID 选择器设置指定按钮的样式)

[4.2.5 后代选择器与子选择器](#4.2.5 后代选择器与子选择器)

示例:后代选择器

示例:子选择器

[4.2.6 并集选择器(Union Selector)](#4.2.6 并集选择器(Union Selector))

示例:设置按钮、标签、输入框的文本颜色都为红色

[4.3 子控件选择器(Sub-Controls)](#4.3 子控件选择器(Sub-Controls))

语法格式

[示例 1:自定义 QComboBox 的下拉箭头](#示例 1:自定义 QComboBox 的下拉箭头)

[示例 2:自定义 QProgressBar 的进度颜色](#示例 2:自定义 QProgressBar 的进度颜色)

[4.4 伪类选择器(Pseudo-States)](#4.4 伪类选择器(Pseudo-States))

常用伪类选择器

示例:自定义按钮的状态样式

对比:伪类选择器与事件方式的实现

[五、QSS 样式属性:定制细节,精益求精](#五、QSS 样式属性:定制细节,精益求精)

[5.1 盒模型(Box Model)](#5.1 盒模型(Box Model))

[5.2 核心样式属性](#5.2 核心样式属性)

[5.3 常用属性示例](#5.3 常用属性示例)

[5.3.1 设置边框和内边距](#5.3.1 设置边框和内边距)

[5.3.2 设置外边距](#5.3.2 设置外边距)

六、控件样式示例:实战演练,美化常用控件

[6.1 按钮(QPushButton)美化](#6.1 按钮(QPushButton)美化)

需求:

[QSS 代码:](#QSS 代码:)

实现步骤:

[6.2 复选框(QCheckBox)美化](#6.2 复选框(QCheckBox)美化)

需求:

实现步骤:

[步骤 1:准备图标资源](#步骤 1:准备图标资源)

[步骤 2:编写 QSS 代码](#步骤 2:编写 QSS 代码)

[步骤 3:应用样式](#步骤 3:应用样式)

[6.3 单选框(QRadioButton)美化](#6.3 单选框(QRadioButton)美化)

需求:

实现步骤:

[步骤 1:准备图标资源](#步骤 1:准备图标资源)

[步骤 2:编写 QSS 代码](#步骤 2:编写 QSS 代码)

[步骤 3:应用样式](#步骤 3:应用样式)

[6.4 输入框(QLineEdit)美化](#6.4 输入框(QLineEdit)美化)

需求:

[QSS 代码:](#QSS 代码:)

应用效果:

[6.5 列表(QListView)美化](#6.5 列表(QListView)美化)

需求:

[QSS 代码:](#QSS 代码:)

关键属性:qlineargradient(线性渐变)

示例:不同方向的渐变

[6.6 菜单栏(QMenuBar)美化](#6.6 菜单栏(QMenuBar)美化)

需求:

[QSS 代码:](#QSS 代码:)

应用效果:

[6.7 登录界面综合美化(实战案例)](#6.7 登录界面综合美化(实战案例))

[6.7.1 界面布局](#6.7.1 界面布局)

[6.7.2 布局设置](#6.7.2 布局设置)

[6.7.3 准备资源](#6.7.3 准备资源)

[6.7.4 完整 QSS 代码](#6.7.4 完整 QSS 代码)

[6.7.5 应用样式](#6.7.5 应用样式)

总结


前言

在 Qt 开发中,功能实现固然重要,但界面的美观度往往直接影响用户体验。想象一下,两个功能完全相同的 Qt 程序,一个界面单调乏味、控件杂乱无章,另一个则布局精致、色彩协调、交互流畅,你会选择哪一个?答案不言而喻。而 QSS(Qt Style Sheets)正是 Qt 为开发者提供的 "界面美化神器",它借鉴了网页开发中 CSS 的设计思想,让我们能够以简洁的语法快速定制 Qt 控件的样式,轻松打造出专业级的精美界面。

本文将从 QSS 的背景介绍、基本语法、设置方式、选择器、样式属性到各类控件的实战示例,进行全方位、手把手的详细讲解,带你从零掌握 QSS 界面优化技巧,让你的 Qt 程序告别 "原生土味",迎来颜值巅峰!下面就让我们正式开始吧!


一、QSS 背景介绍:Qt 中的 "CSS",界面美化的刚需

1.1 为什么需要 QSS?

在网页前端开发中,**CSS(Cascading Style Sheets)**早已成为不可或缺的一部分,它负责描述网页的样式,包括控件大小、位置、颜色、背景、字体等,让原本单调的 HTML 页面变得美观生动。如今,几乎所有的网页都离不开 CSS 的修饰,"界面好看" 已经成为用户对软件的基本诉求。

那么,Qt 开发中是否也需要这样的 "样式美化工具" 呢?答案是肯定的。随着用户对软件体验要求的不断提高,仅仅满足核心功能已经远远不够。一个美观、易用的界面能够提升用户的使用意愿,甚至成为产品的核心竞争力。知乎上有一个热门问题 "软件的界面美观重要吗?",其中高赞回答提到:"美观的界面不仅能给用户带来愉悦的视觉体验,还能间接提升用户对软件功能的信任度"。

Qt 作为一款强大的跨平台 GUI 开发框架,自然也意识到了这一点。它借鉴了 CSS 的设计理念,引入了 QSS(Qt Style Sheets),让开发者能够像使用 CSS 美化网页一样,轻松定制 Qt 控件的样式。除此之外,Qt 还引入了 QML 用于界面描述,甚至支持直接加载原生 HTML 页面,但 QSS 以其简洁易用、与 C++ 代码无缝集成的特点,成为 Qt 界面美化的首选方案。

1.2 QSS 与 CSS 的异同

需要注意的是,QSS 并非完全照搬 CSS,由于 Qt 的设计理念和网页前端存在本质差异,QSS 仅支持部分 CSS 属性,整体语法比 CSS 更简单。这意味着即使你没有 CSS 基础,也能快速上手 QSS;而如果你有 CSS 经验,学习 QSS 更是如虎添翼。

另外一个重要的特性是:当通过 QSS 设置的样式与 C++ 代码设置的样式发生冲突时,QSS 的优先级更高。这一规则让我们能够通过 QSS 灵活覆盖原生控件的默认样式,而无需修改大量 C++ 代码。

二、QSS 基本语法:简单直观,上手即会

QSS 的语法结构与 CSS 高度相似,核心由 "选择器" 和**"属性键值对"** 组成,整体结构简洁明了,非常容易理解。

2.1 核心语法结构

QSS 的基本语法格式如下:

css 复制代码
选择器 {
    属性名1: 属性值1;
    属性名2: 属性值2;
    ...
}
  • 选择器:指定哪些控件会应用该样式规则,例如 "QPushButton" 表示所有按钮控件。
  • 属性键值对:描述具体的样式设置,属性名表示要设置的样式类型(如颜色、字体大小),属性值表示样式的具体参数(如红色、20px)。
  • 注意事项:每个属性键值对末尾必须加上分号(;),即使是最后一个属性也不例外;花括号({})用于包裹属性集合,不可或缺。

2.2 语法示例

我们以设置按钮文本颜色为红色为例,展示 QSS 的两种常见写法(单行和多行):

单行写法

css 复制代码
QPushButton { color: red; }

多行写法

css 复制代码
QPushButton {
    color: red;
}

这两种写法的效果完全一致,均表示将界面上所有 QPushButton 控件的文本颜色设置为红色。多行写法更适合设置多个属性时使用,结构更清晰,便于阅读和维护。

2.3 最简单的 QSS 使用示例

下面通过一个完整的代码示例,演示如何在 Qt 项目中使用 QSS 设置控件样式:

步骤 1:创建 Qt 项目并添加按钮控件

首先,创建一个基于 QWidget 的 Qt 项目,在 UI 设计器中拖拽一个 QPushButton 控件到界面上,默认对象名为 pushButton。

步骤 2:在 C++ 代码中设置 QSS 样式

在 widget.cpp 的构造函数中,通过setStyleSheet方法为按钮设置样式:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 为按钮设置QSS样式,文本颜色改为红色
    ui->pushButton->setStyleSheet("QPushButton { color: red; }");
}

步骤 3:运行效果

编译并运行程序,可以看到按钮的文本颜色已经成功变为红色。需要注意的是,这种直接给单个控件设置样式的方式,仅对该控件生效,如果后续添加其他 QPushButton 控件,它们的文本颜色不会受到影响。

三、QSS 设置方式:灵活多样,按需选择

Qt 提供了多种 QSS 设置方式,分别适用于不同的场景,开发者可以根据项目需求灵活选择。常见的设置方式包括指定控件样式、全局样式、从文件加载样式和通过 Qt Designer 编辑样式四种。

3.1 指定控件样式设置

3.1.1 单个控件样式设置

这种方式是通过调用具体控件的setStyleSheet方法,为该控件单独设置样式,如 2.3 节中的示例所示。代码如下:

cpp 复制代码
// 仅为pushButton按钮设置红色文本样式
ui->pushButton->setStyleSheet("QPushButton { color: red; }");

特点:样式仅作用于目标控件,针对性强,不影响其他控件。

3.1.2 父控件样式设置(子元素继承)

QSS 具有继承特性:给父控件设置的样式,会自动作用于其所有子控件。例如,Widget 是 QPushButton 的父控件,我们给 Widget 设置 QSS 样式,按钮也会受到影响。

代码示例
cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 给父控件Widget设置样式,子控件QPushButton会继承该样式
    this->setStyleSheet("QPushButton { color: red; }");
}

运行效果

运行程序后,界面上的 QPushButton 按钮文本颜色会变为红色,即使没有直接给按钮设置样式。这种方式适合需要让多个子控件保持相同样式的场景,减少重复代码。

3.2 全局样式设置

如果希望整个程序的所有控件都应用统一的样式,例如所有按钮都是红色文本、所有标签都是蓝色文本,可以使用全局样式设置。全局样式通过**QApplicationsetStyleSheet**方法实现。

3.2.1 全局样式的优点

  • 代码更简洁:无需为每个控件单独设置样式,一次设置全局生效。
  • 便于维护:所有样式集中管理,后续修改时只需修改一处。

3.2.2 代码示例

先创建三个按钮:

编辑main.cpp:

cpp 复制代码
#include <QApplication>
#include "Widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 设置全局样式,所有QPushButton的文本颜色都为红色
    a.setStyleSheet("QPushButton { color: red; }");

    Widget w;
    w.show();

    return a.exec();
}
运行效果

在界面上添加多个 QPushButton 控件,运行程序后所有按钮的文本颜色都会变为红色,实现了样式的统一。

3.2.3 QSS 的层叠特性

当全局样式和指定控件样式设置的属性不冲突时,两种样式会叠加生效;如果属性冲突,则指定控件样式的优先级更高(局部覆盖全局)。

代码示例

(1)先创建两个按钮控件:

(2)设置全局样式:所有按钮文本为红色

cpp 复制代码
// main.cpp
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 全局样式:所有QPushButton文本为红色
    a.setStyleSheet("QPushButton { color: red; }");

    Widget w;
    w.show();

    return a.exec();
}

(3)给第一个按钮单独设置字体大小为 50px

cpp 复制代码
// widget.cpp
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 局部样式:第一个按钮字体大小50px
    ui->pushButton->setStyleSheet("QPushButton { font-size: 50px; }");
}
运行效果
  • 第一个按钮:文本颜色为红色(继承全局样式),字体大小为 50px(局部样式),两种样式叠加生效。
  • 其他按钮:仅应用全局样式,文本颜色为红色,字体大小为默认值。

这种层叠特性让样式设置更加灵活,我们可以通过全局样式奠定整体风格,再通过局部样式对个别控件进行个性化调整。

3.3 从文件加载样式表(推荐)

前面介绍的几种方式都是将 QSS 代码硬编码到 C++ 代码中,这种方式存在一个明显的缺点:QSS 代码与 C++ 代码耦合度高,不利于维护。例如,当需要修改样式时,必须修改 C++ 源代码并重新编译。

更好的做法是将 QSS 样式单独写在.qss文件中,然后在程序运行时读取该文件并加载样式。这种方式实现了样式与逻辑的分离,便于后续修改和维护。

3.3.1 实现步骤

步骤 1:创建.qss 文件

在 Qt Creator 中,右键点击项目 -> 新建文件 -> 选择 "General" -> "Empty File",文件名为style.qss(手动输入扩展名.qss),点击 "完成"。

步骤 2:编写 QSS 样式

打开style.qss文件,编写样式代码,例如:

css 复制代码
// style.qss
QPushButton {
    color: red;
    font-size: 20px;
    border: 2px solid #8f8f91;
}
步骤 3:创建资源文件(.qrc)

为了避免使用绝对路径导致的文件找不到问题,我们将style.qss文件添加到 Qt 资源文件中:

  1. 右键点击项目 -> 新建文件 -> 选择 "Qt" -> "Qt Resource File",文件名为resource.qrc,点击 "完成"。
  2. 打开resource.qrc文件,点击 "Add Prefix",默认前缀为 "/"(可修改)。
  3. 点击 "Add Files",选择之前创建的style.qss文件,将其添加到资源文件中。
步骤 4:在 C++ 代码中加载.qss 文件

main.cpp中编写加载函数,读取style.qss文件的内容并设置为全局样式:

cpp 复制代码
#include <QApplication>
#include <QFile>
#include <QString>
#include "Widget.h"

// 加载QSS文件的函数
QString loadQSS() {
    QFile file(":/style.qss"); // 资源文件路径,前缀":/"表示资源文件根目录
    file.open(QFile::ReadOnly); // 以只读方式打开文件
    QString style = file.readAll(); // 读取文件内容
    file.close(); // 关闭文件
    return style;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 加载QSS样式并设置为全局样式
    const QString& style = loadQSS();
    a.setStyleSheet(style);

    Widget w;
    w.show();

    return a.exec();
}

3.3.2 运行效果

编译并运行程序,所有 QPushButton 控件都会应用style.qss中定义的样式:文本红色、字体大小 20px、边框为 2px 灰色实线。

这种方式的优势非常明显:后续修改样式时,只需编辑style.qss文件,无需修改 C++ 代码,也不需要重新编译程序,极大地提高了开发效率和可维护性。

3.4 使用 Qt Designer 编辑样式(可视化操作)

除了通过代码设置 QSS,Qt Designer 还提供了可视化的样式编辑功能,支持实时预览样式效果,非常适合快速调试样式。

3.4.1 操作步骤

步骤 1:在 Qt Designer 中选择控件

打开 UI 设计器,右键点击需要设置样式的控件(例如 QPushButton),在弹出的菜单中选择 "改变样式表..."。

步骤 2:编辑样式表

在弹出的 "编辑样式表" 对话框中,直接输入 QSS 代码,例如:

输入过程中,对话框会实时校验语法正确性,并且 Qt Designer 的预览界面会立即显示样式效果,方便直观地调整样式参数。

步骤 3:保存样式

点击 "OK" 按钮保存样式,此时样式会被以 XML 格式记录到.ui文件中,例如:

XML 复制代码
<property name="styleSheet">
    <string notr="true">QPushButton { color: red; font-size: 18px; background-color: #f0f0f0; }</string>
</property>
步骤 4:运行程序

3.4.2 特点

  • 可视化操作,无需编写 C++ 代码,上手门槛低。
  • 实时预览效果,便于快速调整样式细节。
  • 样式与 UI 文件绑定,无需额外管理.qss 文件,适合简单样式的快速设置。

3.4.3 注意事项

当一个控件的样式不符合预期时,需要排查以下四个可能的样式来源(优先级从高到低):

  1. 控件自身通过 Qt Designer 设置的样式。
  2. 控件通过 C++ 代码调用setStyleSheet设置的样式。
  3. 父控件设置的样式(子元素继承)。
  4. 全局样式(QApplication设置)。

四、QSS 选择器:精准定位,灵活匹配

选择器是 QSS 的核心组成部分,它的作用是精准定位到需要应用样式的控件。QSS 支持多种选择器,语法与 CSS 选择器基本一致,下面我们重点介绍最常用的几种选择器。

4.1 常用选择器概览

选择器类型 语法示例 说明
全局选择器 * 匹配所有控件
类型选择器 QPushButton 匹配所有 QPushButton 及其子类控件
类选择器 .QPushButton 仅匹配所有 QPushButton 控件,不包含子类
ID 选择器 #pushButton_2 匹配 objectName 为 pushButton_2 的控件
后代选择器 QDialog QPushButton 匹配 QDialog 的所有后代(子、孙等)QPushButton
子选择器 QDialog > QPushButton 仅匹配 QDialog 的直接子控件中的 QPushButton
并集选择器 QPushButton, QLabel, QLineEdit 同时匹配 QPushButton、QLabel、QLineEdit 三种控件

4.2 各选择器详细用法与示例

4.2.1 全局选择器(*)

全局选择器匹配界面上的所有控件,常用于设置全局统一的基础样式,例如全局字体、背景色等。

示例
复制代码
* {
    color: blue;
}

运行之后界面上所有控件(按钮、标签、输入框等)的文本颜色都会变为蓝色。

4.2.2 类型选择器(Type Selector)

类型选择器通过控件的类名进行匹配,并且会匹配该类的所有子类控件。这是最常用的选择器之一,适合设置某一类控件的统一样式。

示例 1:设置所有 QPushButton 及其子类的文本颜色为红色
css 复制代码
QPushButton {
    color: red;
}

如果自定义了一个继承自 QPushButton 的 MyPushButton 类,该样式也会自动应用到 MyPushButton 控件上。

示例 2:通过父类选择器匹配子类控件

QPushButton 是 QWidget 的子类,因此使用 QWidget 作为类型选择器时,QPushButton 也会被匹配:

cpp 复制代码
// main.cpp
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // QWidget是QPushButton的父类,类型选择器会匹配子类
    a.setStyleSheet("QWidget { color: red; }");

    Widget w;
    w.show();

    return a.exec();
}

4.2.3 类选择器(Class Selector)

类选择器的语法是在类名前加一个点(.),它仅匹配指定类的控件,不包含子类。这是与类型选择器的核心区别。

示例:类选择器与类型选择器的对比
cpp 复制代码
// 类选择器:仅匹配QWidget类本身,不匹配其子类QPushButton
a.setStyleSheet(".QWidget { color: red; }");

运行之后发现QPushButton 的文本颜色不会改变,因为类选择器不匹配子类。

4.2.4 ID 选择器(ID Selector)

ID 选择器通过控件的objectName属性进行匹配,语法是在objectName前加一个井号(#) 。由于每个控件的objectName是唯一的,ID 选择器可以精准定位到单个控件,优先级最高。

示例:通过 ID 选择器设置指定按钮的样式
  1. 在 UI 设计器中,给三个按钮分别设置objectNamepushButtonpushButton_2pushButton_3
  2. 编写 QSS 样式:
cpp 复制代码
// main.cpp
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QString style = "";
    // 类型选择器:所有按钮文本为黄色(基础样式)
    style += "QPushButton { color: yellow; }";
    // ID选择器:pushButton文本为红色(覆盖基础样式)
    style += "#pushButton { color: red; }";
    // ID选择器:pushButton_2文本为绿色(覆盖基础样式)
    style += "#pushButton_2 { color: green; }";

    a.setStyleSheet(style);

    Widget w;
    w.show();

    return a.exec();
}

运行效果:

  • pushButton:文本红色(ID 选择器生效)。
  • pushButton_2:文本绿色(ID 选择器生效)。
  • pushButton_3:文本黄色(类型选择器生效)。

4.2.5 后代选择器与子选择器

后代选择器匹配父控件的所有后代控件(包括直接子控件和间接子控件),语法是父控件选择器与子控件选择器之间用空格 分隔;子选择器仅匹配父控件的直接子控件,语法是父控件选择器与子控件选择器之间用**大于号(>)**分隔。

示例:后代选择器
css 复制代码
// 匹配QWidget的所有后代(子、孙等)中的QPushButton
QWidget QPushButton {
    color: red;
}
示例:子选择器
css 复制代码
// 仅匹配QWidget的直接子控件中的QPushButton
QWidget > QPushButton {
    color: blue;
}

4.2.6 并集选择器(Union Selector)

并集选择器用于同时匹配多个选择器对应的控件,语法是多个选择器之间用逗号(,)分隔。这种方式可以将相同的样式应用到多个不同类型的控件上,减少重复代码。

示例:设置按钮、标签、输入框的文本颜色都为红色

创建控件:

编写代码:

cpp 复制代码
// main.cpp
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 并集选择器:同时匹配QPushButton、QLabel、QLineEdit
    a.setStyleSheet("QPushButton, QLabel, QLineEdit { color: red; }");

    Widget w;
    w.show();

    return a.exec();
}

运行效果:QPushButton、QLabel、QLineEdit 的文本颜色均变为红色。

4.3 子控件选择器(Sub-Controls)

有些 Qt 控件内部包含了多个 "子控件",例如 QComboBox 的下拉箭头、QSpinBox 的上下按钮、QProgressBar 的进度块等。QSS 提供了子控件选择器(::),可以针对性地设置这些子控件的样式。

语法格式

css 复制代码
父控件选择器::子控件名称 {
    属性名: 属性值;
}

常用的子控件名称可以参考 Qt 官方文档的 "List of Sub-Controls" 章节。

示例 1:自定义 QComboBox 的下拉箭头

  1. 准备一张下拉箭头图片(down.png),添加到资源文件中。
  2. 编写 QSS 样式:
cpp 复制代码
// main.cpp
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QString style = "";
    // 子控件选择器:QComboBox的下拉箭头(down-arrow)
    style += "QComboBox::down-arrow { image: url(:/down.png); }";

    a.setStyleSheet(style);

    Widget w;
    w.show();

    return a.exec();
}

运行效果:QComboBox 的默认下拉箭头被替换为自定义图片。

示例 2:自定义 QProgressBar 的进度颜色

  1. 在 UI 设计器中添加一个 QProgressBar 控件。
  2. 在 Qt Designer 中编辑样式表:
css 复制代码
// 子控件选择器:QProgressBar的进度块(chunk)
QProgressBar::chunk {
    background-color: #FF0000; // 红色进度条
}

调整进度条文本对齐方式:在 UI 设计器的属性编辑器中,将 QProgressBar 的alignment属性设置为AlignHCenter | AlignVCenter(水平居中 + 垂直居中),避免文本位置异常。

运行效果:进度条的进度块显示为红色,文本居中显示。

4.4 伪类选择器(Pseudo-States)

伪类选择器用于根据控件的状态(如鼠标悬停、按下、选中、获取焦点等)来匹配控件,语法是在选择器后加一个冒号(:)和状态名称。当控件处于指定状态时,样式生效;状态消失时,样式失效。

常用伪类选择器

伪类选择器 说明
:hover 鼠标悬停在控件上时
:pressed 鼠标左键按下控件时
:focus 控件获取输入焦点时
:enabled 控件处于可用状态时
:checked 控件被勾选时(如复选框)
:read-only 控件处于只读状态时(如输入框)

伪类选择器支持取反操作 ,即在状态名称前加**!**,例如:!hover表示鼠标离开控件时。

示例:自定义按钮的状态样式

  1. 在 UI 设计器中添加一个 QPushButton 控件。
  2. 编写 QSS 样式:
cpp 复制代码
// main.cpp
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QString style = "";
    // 默认状态:文本红色
    style += "QPushButton { color: red; font-size: 18px; }";
    // 鼠标悬停状态:文本绿色
    style += "QPushButton:hover { color: green; }";
    // 鼠标按下状态:文本蓝色
    style += "QPushButton:pressed { color: blue; }";

    a.setStyleSheet(style);

    Widget w;
    w.show();

    return a.exec();
}

运行效果:

  • 默认状态:按钮文本红色,字体大小 18px。

  • 鼠标悬停:文本变为绿色。

  • 鼠标按下:文本变为蓝色。

对比:伪类选择器与事件方式的实现

实现上述效果,也可以通过重写按钮的事件函数(如enterEventleaveEventmousePressEvent)来实现,但代码会复杂很多:

cpp 复制代码
// mypushbutton.h
#include <QPushButton>

class MyPushButton : public QPushButton
{
    Q_OBJECT
public:
    MyPushButton(QWidget* parent);

    // 重写事件函数
    void mousePressEvent(QMouseEvent* e) override;
    void mouseReleaseEvent(QMouseEvent* e) override;
    void enterEvent(QEvent* e) override;
    void leaveEvent(QEvent* e) override;
};

// mypushbutton.cpp
#include "mypushbutton.h"

MyPushButton::MyPushButton(QWidget* parent) : QPushButton(parent)
{
    // 默认样式:文本红色
    this->setStyleSheet("QPushButton { color: red; font-size: 18px; }");
}

// 鼠标按下事件
void MyPushButton::mousePressEvent(QMouseEvent *e)
{
    this->setStyleSheet("QPushButton { color: blue; font-size: 18px; }");
}

// 鼠标释放事件
void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
{
    this->setStyleSheet("QPushButton { color: green; font-size: 18px; }");
}

// 鼠标进入事件(悬停)
void MyPushButton::enterEvent(QEvent *e)
{
    this->setStyleSheet("QPushButton { color: green; font-size: 18px; }");
}

// 鼠标离开事件
void MyPushButton::leaveEvent(QEvent *e)
{
    this->setStyleSheet("QPushButton { color: red; font-size: 18px; }");
}

对比可以发现,使用伪类选择器只需几行 QSS 代码就能实现相同的效果,代码更简洁、维护成本更低。但需要注意的是,事件方式可以实现更复杂的业务逻辑(如按下按钮时执行网络请求),而伪类选择器仅用于样式控制,两者各有侧重。

五、QSS 样式属性:定制细节,精益求精

QSS 提供了丰富的样式属性,用于控制控件的各种视觉细节,包括颜色、字体、边框、边距、背景等。大部分属性与 CSS 属性类似,下面我们重点介绍核心属性,并结合 "盒模型" 概念帮助大家理解。

5.1 盒模型(Box Model)

在 QSS 中,所有控件都遵循 "盒模型" 结构,这是理解边距、边框、内边距等属性的基础。盒模型从外到内分为四个部分:

  1. Margin(外边距):控件边框到父控件边界的距离,用于控制控件与其他控件之间的间距。
  2. Border(边框):控件的边框,包括边框宽度、颜色、样式。
  3. Padding(内边距):控件边框到内容区域(如文本、图标)的距离,用于控制内容与边框之间的间距。
  4. Content(内容区域):控件的核心内容区域,如按钮的文本、标签的文字、图片等。

默认情况下,外边距(margin)、内边距(padding)、边框宽度(border-width)均为 0。

5.2 核心样式属性

属性名称 说明 示例值
color 文本颜色 red、#FF0000、rgb(255,0,0)
font-size 字体大小 16px、20pt
font-family 字体类型 "微软雅黑"、"华文行楷"
background-color 背景颜色 #F5F5F5、rgb(245,245,245)
background-image 背景图片 url(:/bg.png)
border 边框复合属性(宽度 + 样式 + 颜色) 2px solid #8f8f91
border-width 边框宽度 2px、5px
border-style 边框样式 solid(实线)、dashed(虚线)等
border-color 边框颜色 #8f8f91、rgb(143,143,145)
border-radius 边框圆角半径(实现圆角控件) 10px、15px
margin 外边距(复合属性) 10px、5px 10px 15px 20px(上右下左)
padding 内边距(复合属性) 8px、3px 6px(上下、左右)

5.3 常用属性示例

5.3.1 设置边框和内边距

创建一个label控件:

cpp 复制代码
// main.cpp
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 设置QLabel的边框和内边距
    a.setStyleSheet("QLabel { "
                   "border: 5px solid red; " // 边框:5px红色实线
                   "padding-left: 10px; "   // 左内边距:10px
                   "font-size: 16px; "      // 字体大小:16px
                   "}");

    Widget w;
    w.show();

    return a.exec();
}

运行效果:QLabel 控件显示红色边框,文本距离左边框 10px,字体大小 16px。

5.3.2 设置外边距

cpp 复制代码
// 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); // 初始位置(0,0),大小100x100
    btn->setText("hello");
    // 设置边框和外边距
    btn->setStyleSheet("QPushButton { "
                       "border: 5px solid red; " // 边框:5px红色实线
                       "margin: 20px; "          // 外边距:20px
                       "}");

    // 输出按钮的几何位置(仍然是0,0,100,100)
    const QRect& rect = btn->geometry();
    qDebug() << rect;
}

运行效果:按钮的实际显示位置会被外边距挤压,距离父控件边界 20px,但geometry()方法返回的位置仍然是初始设置的 (0,0),因为外边距不影响控件的几何位置,仅影响显示布局。

六、控件样式示例:实战演练,美化常用控件

前面我们学习了 QSS 的基础语法、选择器和属性,下面通过多个实战示例,详细讲解如何使用 QSS 美化 Qt 中最常用的控件,包括按钮、复选框、单选框、输入框、列表、菜单栏等,让你直接套用即可。

6.1 按钮(QPushButton)美化

需求:

实现一个圆角按钮,默认状态为浅灰色背景、黑色文本,鼠标悬停时背景变深,按下时背景变浅白色。

QSS 代码:
cpp 复制代码
QPushButton {
    font-size: 20px;          // 字体大小20px
    border: 2px solid #8f8f91; // 边框2px灰色实线
    border-radius: 15px;      // 圆角半径15px
    background-color: #dadbde; // 默认背景色
    padding: 8px 16px;        // 内边距:上下8px,左右16px
}

QPushButton:pressed {
    background-color: #f6f7fa; // 按下时背景色
    border-style: inset;      // 按下时边框凹陷效果
}
实现步骤:
  1. 在 Qt Designer 中添加 QPushButton 控件。
  2. 右键点击按钮 -> "改变样式表",粘贴上述 QSS 代码。
  3. 运行程序,即可看到美化后的按钮效果。

6.2 复选框(QCheckBox)美化

需求:

自定义复选框的图标,默认状态为黑色图标,鼠标悬停时为蓝色,按下时为红色,选中和未选中状态分别对应不同图标。

实现步骤:

步骤 1:准备图标资源

从阿里巴巴矢量图标库(https://www.iconfont.cn/)下载以下图标(可自定义颜色):

  • 未选中状态:checkbox-unchecked.png(黑色)
  • 未选中悬停:checkbox-unchecked_hover.png(蓝色)
  • 未选中按下:checkbox-unchecked_pressed.png(红色)
  • 选中状态:checkbox-checked.png(黑色)
  • 选中悬停:checkbox-checked_hover.png(蓝色)
  • 选中按下:checkbox-checked_pressed.png(红色)

将图标添加到资源文件中。

步骤 2:编写 QSS 代码
css 复制代码
QCheckBox {
    font-size: 20px;          // 字体大小20px
    color: #333;              // 文本颜色
}

// 子控件选择器:选中复选框的图标部分
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);
}
步骤 3:应用样式

在 Qt Designer 中给 QCheckBox 控件设置上述样式,运行程序后,复选框会根据不同状态显示对应的图标。

6.3 单选框(QRadioButton)美化

需求:

与复选框类似,自定义单选框的图标,支持默认、悬停、按下、选中四种状态。

实现步骤:

步骤 1:准备图标资源

下载以下图标并添加到资源文件:

  • 未选中状态:radio-unchecked.png(黑色)
  • 未选中悬停:radio-unchecked_hover.png(蓝色)
  • 未选中按下:radio-unchecked_pressed.png(红色)
  • 选中状态:radio-checked.png(黑色)
  • 选中悬停:radio-checked_hover.png(蓝色)
  • 选中按下:radio-checked_pressed.png(红色)
步骤 2:编写 QSS 代码
css 复制代码
// 后代选择器:匹配QWidget下的所有QRadioButton
QWidget QRadioButton {
    font-size: 20px;
    color: #333;
}

// 子控件选择器:选中单选框的图标部分
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);
}
步骤 3:应用样式

将样式设置到父控件 QWidget 上(确保所有 QRadioButton 都能继承),运行程序即可看到效果。

6.4 输入框(QLineEdit)美化

需求:

实现一个深色风格的输入框,圆角边框,白色文本,选中文字时背景色为浅灰色、文本色为深灰色。

QSS 代码:

css 复制代码
QLineEdit {
    border-width: 1px;          // 边框宽度1px
    border-radius: 10px;        // 圆角半径10px
    border-color: rgb(58, 58, 58); // 边框颜色深灰色
    border-style: inset;        // 边框凹陷风格
    padding: 0 8px;             // 左右内边距8px
    color: rgb(255, 255, 255);  // 文本颜色白色
    background: rgb(100, 100, 100); // 背景色灰色
    font-size: 18px;            // 字体大小18px
    selection-background-color: rgb(187, 187, 187); // 选中文字背景色
    selection-color: rgb(60, 63, 65); // 选中文字文本色
}

应用效果:

输入框显示为深色圆角样式,文本居中对齐(左右内边距 8px),选中文字时呈现深灰色背景和白色文本。

6.5 列表(QListView)美化

需求:

自定义列表项的样式,鼠标悬停时显示渐变色背景,选中时显示深蓝色边框和渐变背景。

QSS 代码:

css 复制代码
// 列表项悬停样式
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); // 深蓝色渐变
    color: white; // 选中时文本白色
}

关键属性:qlineargradient(线性渐变)

qlineargradient用于设置线性渐变背景,参数说明:

  • x1, y1:渐变起点坐标(0,0 表示左上角)。
  • x2, y2:渐变终点坐标(0,1 表示垂直向下,1,0 表示水平向右)。
  • stop: 0:渐变起始颜色。
  • stop: 1:渐变结束颜色。

示例:不同方向的渐变

css 复制代码
// 垂直从上到下:白色→黑色
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fff, stop:1 #000);

// 水平从左到右:白色→黑色
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #fff, stop:1 #000);

// 左上到右下:白色→黑色
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #fff, stop:1 #000);

6.6 菜单栏(QMenuBar)美化

需求:

自定义菜单栏和菜单的样式,菜单栏显示渐变背景,菜单项悬停时显示灰色背景,选中时显示深蓝色边框。

QSS 代码:

css 复制代码
// 菜单栏样式
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; // 右边距
}

应用效果:

菜单栏显示浅灰色到深灰色的渐变背景,菜单项悬停时显示灰色背景,下拉菜单选中项显示深蓝色边框和半透明背景,分隔线为浅蓝色。

6.7 登录界面综合美化(实战案例)

下面我们结合前面学习的知识,打造一个完整的美化登录界面,包含背景图片、自定义输入框、复选框和登录按钮。

6.7.1 界面布局

在 UI 设计器中创建以下控件,并使用 QVBoxLayout 进行布局:

  1. 两个 QLineEdit:分别用于输入用户名和密码(objectName:leUsername、lePassword)。
  2. 一个 QCheckBox:用于 "记住密码"(objectName:cbRemember)。
  3. 一个 QPushButton:登录按钮(objectName:btnLogin)。
  4. 一个 QFrame:作为父容器,用于设置背景图片(objectName:frame)。

6.7.2 布局设置

  • 将所有控件添加到 QVBoxLayout 中,设置布局间距为 20px,边距为 30px。
  • 设置 QLineEdit 和 QPushButton 的minimumHeight为 50px,确保控件高度足够。
  • 将 QCheckBox 的对齐方式设置为左对齐(右键 -> Layout Alignment -> AlignLeft)。

6.7.3 准备资源

添加一张背景图片(如 cat.jpg)到资源文件中。

6.7.4 完整 QSS 代码

css 复制代码
// 父容器QFrame:设置背景图片(自动缩放)
QFrame {
    border-image: url(:/cat.jpg); // 背景图片(border-image支持缩放)
}

// 用户名/密码输入框样式
QLineEdit {
    color: #8d98a1; // 文本颜色
    background-color: #405361; // 背景色
    padding: 0 5px; // 左右内边距
    font-size: 20px; // 字体大小
    border-style: none; // 无边框
    border-radius: 10px; // 圆角
}

// 记住密码复选框样式
QCheckBox {
    color: white; // 文本颜色白色
    background-color: transparent; // 透明背景(继承父容器背景)
    font-size: 16px; // 字体大小
}

// 复选框图标样式
QCheckBox::indicator {
    width: 18px;
    height: 18px;
}

QCheckBox::indicator:unchecked {
    image: url(:/checkbox-unchecked.png);
}

QCheckBox::indicator:checked {
    image: url(:/checkbox-checked.png);
}

// 登录按钮样式
QPushButton {
    font-size: 20px; // 字体大小
    color: white; // 文本颜色
    background-color: #555; // 背景色
    border-style: outset; // 边框凸起风格
    border-radius: 10px; // 圆角
    border-width: 2px;
    border-color: #777;
}

QPushButton:pressed {
    color: black; // 按下时文本黑色
    background-color: #ced1db; // 按下时背景色
    border-style: inset; // 按下时边框凹陷
}

6.7.5 应用样式

将上述 QSS 代码设置到 QFrame 控件上(右键 -> 改变样式表),运行程序即可看到美化后的登录界面。​​​​​​​


总结

通过本文的学习,相信你已经掌握了 QSS 的核心用法和实战技巧。QSS 作为 Qt 界面美化的核心工具,能够帮助你快速提升程序的视觉体验。建议在实际项目中多动手实践,结合设计稿灵活运用各种选择器的和属性,打造出既美观又实用的 Qt 界面。如果在使用过程中遇到问题,可以参考 Qt 官方文档或开源项目的示例,不断积累经验。祝你在 Qt 开发之路上越走越远!

相关推荐
e***98572 小时前
Java性能优化实战:从原理到案例
java·开发语言·性能优化
HellowAmy2 小时前
我的C++规范 - 跳跃的对象
开发语言·c++·代码规范
lph0092 小时前
QtMqtt 的编译与QT环境加载配置
开发语言·qt
lucky-billy2 小时前
架构设计 - std::forward 条件转换配合万能引用(T&&)来实现完美转发
c++·完美转发·forward·万能引用
崇山峻岭之间2 小时前
Matlab学习记录35
开发语言·学习·matlab
bkspiderx2 小时前
C/C++中float浮点型的存储方式与使用要点
c++
机器视觉知识推荐、就业指导2 小时前
Qt 小技巧:如何用 Q_PROPERTY 管理属性
服务器·数据库·qt
比奇堡派星星3 小时前
Linux OOM Killer
linux·开发语言·arm开发·驱动开发
hqwest3 小时前
码上通QT实战11--监控页面03-绘制湿度盘和亮度盘
开发语言·qt·绘图·自定义组件·部件·qpainter·温度盘