Qt进阶开发:QSS常用的语法介绍和使用

一、什么是QSS?

  在 Qt 中,QSS(Qt Style Sheets) 是一种用于美化界面外观的技术,它的语法类似于 CSS(层叠样式表),但针对的是 Qt 的控件。QSS 可以让你在不改动控件代码的前提下,对 Qt 界面中的控件进行灵活、统一的样式定制。

QSS 可以控制 Qt 应用中的以下方面:

  • 控件的背景颜色、文字颜色、边框、圆角、字体等;
  • 控件的状态(如 hover、pressed、disabled)样式;
  • 自定义控件的外观,打造现代化 UI;
  • 控件的子控件样式(如 QScrollBar 的 handle、add-line、sub-line 等)。

二、QSS的基本语法

QSS 的语法基本与 CSS 相似,基本格式如下:

QPushButton {
    background-color: #3498db;
    color: white;
    border: 1px solid #2980b9;
    border-radius: 5px;
    padding: 5px 10px;
}

QPushButton:hover {
    background-color: #2980b9;
}

QPushButton:pressed {
    background-color: #1abc9c;
}

上述 QSS 应用于 QPushButton,定义了其正常、鼠标悬浮、按下时的不同状态样式。

三、QSS 的使用方式

3.1 在代码中设置 QSS

QPushButton *btn = new QPushButton("Click me");
btn->setStyleSheet("background-color: red; color: white; border-radius: 5px;");

3.2 加载外部 QSS 文件

QFile file(":/styles/my_style.qss");
if (file.open(QFile::ReadOnly)) {
    QString styleSheet = QLatin1String(file.readAll());
    qApp->setStyleSheet(styleSheet);  // 设置应用级样式
}

四、QSS中选择器的介绍和使用

4.1 Type Selector(类型选择器)

  类型选择器是 QSS(Qt Style Sheets)中最基础也最常用的一类选择器,用于根据控件的类名(类型)来匹配并设置样式。它的语法非常简单,直接写控件的类型名即可。

语法格式:

QWidgetType {
    /* 样式定义 */
}

其中 QWidgetType 是 Qt 控件的类名,例如:QPushButton, QLabel, QLineEdit 等。

示例一:设置所有按钮样式

QPushButton {
    background-color: #3498db;
    color: white;
    border-radius: 5px;
    padding: 6px 12px;
}

这个样式会应用到程序中所有的 QPushButton 控件上。

示例二:统一设置所有标签文字颜色

QLabel {
    color: #2c3e50;
    font-weight: bold;
}

无论标签显示在哪个位置,这条规则都会生效。

示例三:组合状态伪类

QPushButton:hover {
    background-color: #2980b9;
}

QPushButton:pressed {
    background-color: #1abc9c;
}

用于细化交互状态下的样式。

4.2 ID Selector(ID 选择器)

  ID 选择器(又称对象名选择器)是 Qt Style Sheets(QSS)中用于精确匹配某个特定控件的选择器。通过设置控件的 objectName,可以为这个控件单独定义样式,而不会影响同类其他控件。

4.2.1 仅使用 ID(常见写法)

语法格式:

#objectName {
    /* 样式定义 */
}
  • # 表示按控件的 objectName 匹配;
  • objectName 是通过 setObjectName(“name”) 设置的标识。

使用步骤:
在 QSS 中使用 ID Selector

#confirmBtn {
    background-color: #27ae60;
    color: white;
    border-radius: 4px;
    padding: 6px 12px;
}

设置控件的 objectName(C++ 中)

QPushButton *btn = new QPushButton("确定");
btn->setObjectName("confirmBtn");

这个样式只会应用到 objectName 为 confirmBtn 的按钮。

示例:多个按钮不同样式

#okButton {
    background-color: #2ecc71;
}

#cancelButton {
    background-color: #e74c3c;
}
QPushButton *okBtn = new QPushButton("OK");
okBtn->setObjectName("okButton");

QPushButton *cancelBtn = new QPushButton("Cancel");
cancelBtn->setObjectName("cancelButton");

结合状态伪类使用:

#okButton:hover {
    background-color: #27ae60;
}

#cancelButton:pressed {
    background-color: #c0392b;
}
4.2. 2 类型 + ID(更精确匹配)

语法格式:

QWidgetType#objectName {
    /* 样式定义 */
}

表示只有 QWidgetType 类型,并且 objectName == “myButton” 才会应用此样式。

带类型限定的 ID 选择器:

/* 主窗口背景 */
QMainWindow {
    background-color: #f0f2f5;
}

/* 标题标签 */
QLabel#titleLabel {
    font-size: 20px;
    font-weight: bold;
    color: #2c3e50;
    margin-bottom: 12px;
}

/* 输入框:搜索框 */
QLineEdit#searchInput {
    background-color: white;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    padding: 6px 10px;
}

/* 确认按钮 */
QPushButton#confirmBtn {
    background-color: #409EFF;
    color: white;
    border-radius: 4px;
    padding: 6px 16px;
}

QPushButton#confirmBtn:hover {
    background-color: #66b1ff;
}

QPushButton#confirmBtn:pressed {
    background-color: #337ecc;
}

/* 取消按钮 */
QPushButton#cancelBtn {
    background-color: #e6e6e6;
    color: #606266;
    border-radius: 4px;
    padding: 6px 16px;
}

QPushButton#cancelBtn:hover {
    background-color: #dcdcdc;
}

QPushButton#cancelBtn:pressed {
    background-color: #c0c0c0;
}

对应控件设置代码(C++):

QPushButton* confirmBtn = new QPushButton("确认");
confirmBtn->setObjectName("confirmBtn");

QPushButton* cancelBtn = new QPushButton("取消");
cancelBtn->setObjectName("cancelBtn");

QLabel* titleLabel = new QLabel("欢迎使用系统");
titleLabel->setObjectName("titleLabel");

QLineEdit* searchInput = new QLineEdit;
searchInput->setObjectName("searchInput");

4.3 Class Selector(类选择器)

  在标准的 CSS 中,“类选择器”是通过 . 来匹配 class 属性的,但在 Qt 的 QSS 中,“类选择器” 实际上是指“类型选择器”,用于匹配控件的类名(如 QPushButton、QLabel),而不是 CSS 那种 .className 的方式。

不过,为了方便理解和对比,有时也会口语上把下面这几种情况称作“类选择器”:
在这里插入图片描述
QSS 并不支持像 CSS 中的 .className 类似的“类名选择器”;Qt 的控件并没有 class 属性,也不能直接用 .className 匹配。
我们可以以继承自一个控件类型,例如 QPushButton,然后在 QSS 中写你自定义的类名。

// mybutton.h
class MyButton : public QPushButton {
    Q_OBJECT
public:
    explicit MyButton(QWidget* parent = nullptr);
};
MyButton {
    background-color: #8e44ad;
    color: white;
}

这样写就像 CSS 的 .my-button 一样作用于你所有的 MyButton 控件。

4.4 Universal Selector(通用选择器)

通用选择器(*) 是一种 匹配所有控件的选择器,用于为整个界面或某个控件的所有子控件设置统一的样式。

基本语法:

* {
    font-family: "Microsoft YaHei";
    font-size: 14px;
    color: #2c3e50;
}

表示界面中所有控件都应用上述样式。

示例 1:全局统一字体和颜色

* {
    font-family: "微软雅黑";
    font-size: 13px;
    color: #333333;
}

适合用于统一整个应用的控件风格,如设置字体、文字颜色等。

示例 2:限定某控件的所有子控件

QWidget * {
    background-color: #f9f9f9;
}

这表示 QWidget 的所有子控件都使用背景色 #f9f9f9。

示例 3:配合更具体的规则使用
可以用 * 设置基础样式,再用其他选择器进行细化覆盖:

* {
    font-size: 12px;
    color: #555;
}

QLabel#titleLabel {
    font-size: 18px;
    font-weight: bold;
    color: #2c3e50;
}

注意事项:

  • * 的权重很低,更具体的选择器会覆盖它的效果;
  • 不要用它设置所有控件的背景色,否则可能会导致控件嵌套层级混乱(特别是 QScrollArea、QGroupBox 等);
  • 不推荐用 * 设置控件大小、边框、内边距等结构性样式,容易引发样式冲突;

4.5 属性选择器(Attribute Selector)

属性选择器允许你根据控件的某个Qt 属性值来选择性地应用样式。

基本语法:

控件类型[属性名="属性值"] {
    /* 样式 */
}

自定义属性的使用建议:

  • 使用 setProperty(“key”, “value”) 在代码中动态设置;
  • 记得在修改后调用 style()->unpolish() 和 style()->polish() 使样式刷新(可选)。
unpolish() 和 polish() 的作用

  在 Qt 中,style()->unpolish() 和 style()->polish() 主要用于强制刷新控件的样式,当我们修改了 setProperty() 之后,QSS 不能自动识别更改时,需要手动触发样式重新应用。

unpolish(QWidget *widget):

  • 移除当前应用在控件上的 QSS 样式。
  • 使控件恢复 Qt 默认样式(但不主动重绘)。

polish(QWidget *widget):

  • 重新应用 QSS 样式。
  • 如果控件的属性(如 setProperty())发生变化,必须调用 polish() 才能生效。
  • 也会重新执行 paintEvent(),从而刷新 UI。
为什么需要 unpolish() + polish()?
  • 直接使用 setProperty() 不会自动触发 QSS 更新,所以 QSS 需要手动刷新。
  • setStyleSheet() 会刷新整个应用,性能消耗大。而 polish() 只刷新一个控件,性能更好。

在这里插入图片描述

例如:

myWidget->setProperty("level", "warning");
myWidget->style()->unpolish(myWidget);
myWidget->style()->polish(myWidget);

示例 1:控制是否启用的样式

QLineEdit {
    background-color: white;
    color: black;
}

QLineEdit:disabled {
    background-color: #eee;
    color: #aaa;
}
#include <QApplication>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

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

    QWidget window;
    window.setWindowTitle("QLineEdit enabled 属性演示");

    QLineEdit* edit = new QLineEdit;
    edit->setPlaceholderText("请输入内容...");

    QPushButton* toggleBtn = new QPushButton("启用/禁用");

    QObject::connect(toggleBtn, &QPushButton::clicked, [=]() mutable {
        edit->setEnabled(!edit->isEnabled());
    });

    QVBoxLayout* layout = new QVBoxLayout;
    layout->addWidget(edit);
    layout->addWidget(toggleBtn);
    window.setLayout(layout);

    // 设置样式表
    app.setStyleSheet(R"(
        QLineEdit {
            background-color: white;
            color: black;
            border: 1px solid #ccc;
            padding: 4px;
        }

        QLineEdit:disabled {
            background-color: #eee;
            color: #aaa;
        }
    )");

    window.show();
    return app.exec();
}

当QLineEdit设置为disabled时,会自动匹配QSS 对应规则。即QLineEdit:disabled。

示例 2:QPushButton 设置自定义属性控制样式
设置一个属性:

QPushButton[level="danger"] {
    background-color: #e74c3c;
    color: white;
}

QPushButton[level="primary"] {
    background-color: #409EFF;
    color: white;
}
myButton->setProperty("level", "danger");

下面是一个 完整的 Qt 示例,展示如何使用 QSS 中的 属性选择器 来动态改变按钮的样式 :
QSS 样式文件:

QPushButton[level="primary"] {
    color: white;
    background-color: #3498db;
    border: 2px solid #2980b9;
    border-radius: 6px;
    padding: 6px 12px;
    font-size: 16px;
}

QPushButton[level="primary"]:hover {
    background-color: #5dade2;
}

QPushButton[level="primary"]:pressed {
    background-color: #2e86c1;
}

QPushButton[level="danger"] {
    color: white;
    background-color: #e74c3c;
    border: 2px solid #c0392b;
    border-radius: 6px;
    padding: 6px 12px;
    font-size: 16px;
}

QPushButton[level="danger"]:hover {
    background-color: #ec7063;
}

QPushButton[level="danger"]:pressed {
    background-color: #cb4335;
}

代码实现:

#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QFile>
#include <QStyle>

void updateButtonStyle(QPushButton* button, const QString& level) {
    button->setProperty("level", level);
    button->style()->unpolish(button);
    button->style()->polish(button);
}

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

    QWidget window;
    window.setWindowTitle("属性选择器示例");

    QPushButton* btn = new QPushButton("点击切换风格");
    btn->setFixedSize(200, 40);

    // 初始设置属性
    updateButtonStyle(btn, "primary");

    // 切换属性值
    QObject::connect(btn, &QPushButton::clicked, [=]() mutable {
        QString current = btn->property("level").toString();
        QString next = (current == "primary") ? "danger" : "primary";
        updateButtonStyle(btn, next);
    });

    QVBoxLayout* layout = new QVBoxLayout;
    layout->addWidget(btn);
    window.setLayout(layout);

    // 加载样式表
    QFile qss(":/res/qss_style.qss");
    if (qss.open(QFile::ReadOnly)) {
        app.setStyleSheet(qss.readAll());
    }

    window.show();
    return app.exec();
}

输出结果:
请添加图片描述

下面是一个完整的 Qt 示例,演示如何通过按钮在深色模式和浅色模式之间切换 UI 主题:

要让主题设置全局生效,不仅影响 QWidget 主窗口,还影响所有子控件(如 QLabel, QLineEdit, QPushButton 等)

QSS 样式文件:

/* 浅色主题 */
*[theme="light"] {
    background-color: #f9f9f9;
    color: #000;
}

QLineEdit[theme="light"] {
    background-color: white;
    border: 1px solid #ccc;
    color: #000;
}

QPushButton[theme="light"] {
    background-color: #e0e0e0;
    color: #000;
}

/* 深色主题 */
*[theme="dark"] {
    background-color: #2c3e50;
    color: #ecf0f1;
}

QLineEdit[theme="dark"] {
    background-color: #34495e;
    border: 1px solid #95a5a6;
    color: #ecf0f1;
}

QPushButton[theme="dark"] {
    background-color: #3b5998;
    color: white;
}

优点:

  • 无需对子控件逐一设置属性;
  • 所有控件自动响应主题切换;
  • 支持自定义属性驱动任意 QSS 控制逻辑。

代码实现:

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QFile>
#include <QStyle>

void applyTheme(QWidget* window, const QString& theme) {
    window->setProperty("theme", theme);
    window->style()->unpolish(window);
    window->style()->polish(window);
}

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

    // 主窗口
    QWidget window;
    window.setWindowTitle("主题切换示例");

    // 设置初始主题
    applyTheme(&window, "light");

    // 控件
    QLabel* label = new QLabel("请输入用户名:");
    QLineEdit* edit = new QLineEdit;
    QPushButton* switchBtn = new QPushButton("切换主题");

    // 布局
    QVBoxLayout* layout = new QVBoxLayout;
    layout->addWidget(label);
    layout->addWidget(edit);
    layout->addWidget(switchBtn);
    window.setLayout(layout);

    // 切换按钮事件
    QObject::connect(switchBtn, &QPushButton::clicked, [&]() {
        QString current = window.property("theme").toString();
        QString next = (current == "light") ? "dark" : "light";
        applyTheme(&window, next);
    });

    // 加载样式表
    QFile file(":/res/qss_style.qss");
    if (file.open(QFile::ReadOnly)) {
        app.setStyleSheet(file.readAll());
    }

    window.show();
    return app.exec();
}

输出结果:
在这里插入图片描述

4.6 Pseudo-class Selector(伪类选择器)

  在 Qt 的 QSS(Qt Style Sheets)中,伪类选择器(Pseudo-class Selector) 是用于根据控件状态(如悬停、按下、选中、禁用等)来改变控件样式的强大工具。它类似于 CSS 中的伪类,例如 :hover、:checked 等。

常用的伪类选择器一览
在这里插入图片描述
示例:按钮的悬停与按下状态样式

QPushButton {
    background-color: #3498db;
    color: white;
    border-radius: 5px;
    padding: 6px 12px;
}

QPushButton:hover {
    background-color: #2980b9; /* 鼠标悬停变深 */
}

QPushButton:pressed {
    background-color: #1c5980; /* 鼠标按下再变深 */
}

以下是一个完整 Qt 示例程序,用于动态演示伪类(Pseudo-class)视觉效果:

QSS 样式文件:

QPushButton {
    background-color: #3498db;
    color: white;
    border: none;
    border-radius: 6px;
    padding: 8px;
}

QPushButton:hover {
    background-color: #2980b9;
}

QPushButton:pressed {
    background-color: #1c5980;
}

QPushButton:disabled {
    background-color: #cccccc;
    color: #888888;
}

QLineEdit {
    border: 2px solid #cccccc;
    border-radius: 4px;
    padding: 4px;
}

QLineEdit:focus {
    border: 2px solid #0078d7;
    background-color: #eef6ff;
}

QCheckBox::indicator {
    width: 18px;
    height: 18px;
}

QCheckBox::indicator:checked {
    image: url(:/icons/checkbox_checked.png);
}

QCheckBox::indicator:unchecked {
    image: url(:/icons/checkbox_unchecked.png);
}

代码实现:

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QCheckBox>
#include <QFile>

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

    QWidget window;
    window.setWindowTitle("伪类选择器演示");

    QVBoxLayout* layout = new QVBoxLayout;

    // 按钮 - hover & pressed
    QPushButton* button = new QPushButton("悬停 / 按下效果");

    // QLineEdit - focus
    QLineEdit* edit = new QLineEdit;
    edit->setPlaceholderText("点击这里以获得焦点");

    // QCheckBox - checked
    QCheckBox* checkbox = new QCheckBox("启用功能");

    // Disabled 按钮
    QPushButton* disabledBtn = new QPushButton("禁用按钮");
    disabledBtn->setEnabled(false);

    layout->addWidget(button);
    layout->addWidget(edit);
    layout->addWidget(checkbox);
    layout->addWidget(disabledBtn);

    window.setLayout(layout);

    // 加载 QSS
    QFile file(":/res/qss_style.qss");
    if (file.open(QFile::ReadOnly)) {
        app.setStyleSheet(file.readAll());
    }

    window.show();
    return app.exec();
}

输出结果:
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值