本页内容

用于Qt Widgets

Qt Widgets 提供了三种改变控件外观的方法:

  • style 负责绘制每个小部件。通过继承QProxyStyle 来调整平台样式,或继承QCommonStyle 来实现完全自定义的外观。这是 Qt 自身样式所采用的机制,也是生产级应用程序中应采用的方式。
  • StyleKit通过 QML 以声明式方式描述设计,并通过 `QStyleKitStyle`(即 `QStyle ` 的实现)将其应用于小部件。同一样式文件也会为 `Qt Quick Controls` 设置样式。
  • 样式表通过类似 CSS 的规则覆盖单个视觉属性。它们是用于原型设计和进行小范围局部调整的工具,而非用于应用程序的正式外观设计。

本页说明了每种方法的代价以及何时选择它。

选择方法

下表将样式设计目标与相应的实现机制进行了对应。

目标方法
保留原生外观,但修改一些细节,例如度量值、颜色或样式提示QProxyStyle 的子类
为应用程序赋予独立于平台样式的独特外观,例如在嵌入式设备上QCommonStyle 的子类或 StyleKit 样式
在Qt Widgets 和Qt Quick ControlsStyleKit样式
为同一设计提供浅色和深色变体针对同一样式使用不同的 `QPalette `,或使用 StyleKit 主题
在开发过程中快速尝试颜色、边框和间距,或重新设计单个小部件样式表

为生产环境应用程序实现样式

QStyle 的子类会使用 `QPainter` 直接绘制控件,并利用每个控件传递给样式的 `QStyleOption ` 中的信息。 样式可以完全控制每个元素,从按钮的斜面到树视图的分支,并且只需进行一次普通的绘制操作即可实现这种控制:无需匹配规则,也无需重新计算每个控件的状态。

请根据您希望进行的修改程度选择基类:

  • QProxyStyle 封装另一个样式(默认是平台样式),允许你重写选定的函数,例如drawPrimitive()、pixelMetric() 或styleHint()。所有未被重写的部分都将保留原生外观和行为。使用它来调整平台样式。
  • QCommonStyle 实现所有 Qt 样式共有的行为,并将绘制工作交由您处理。将其用作完整自定义外观的基础。《样式与感知样式的小部件》一节详细介绍了样式元素,并展示了每个小部件的绘制过程。

在应用程序创建窗口之前,先设置一次样式:

#include <QtWidgets>

#include "customstyle.h"

int main(int argc, char *argv[])
{
    QApplication::setStyle(new CustomStyle);
    QApplication app(argc, argv);
    QSpinBox spinBox;
    spinBox.show();
    return app.exec();
}

使用样式选项中QPalette 定义的颜色进行绘制,而非硬编码的颜色。这样,同一种样式即可通过两组调色板生成设计方案的浅色和深色变体,而无需切换样式。Qt的Fusion样式便是如此运作的。

若要让用户通过命令行中的-style 选项选择样式,或在应用程序之间共享样式,请将样式构建为插件。请参阅《Qt XML 样式指南》(QStylePlugin )和《如何创建 Qt 插件》(How to Create Qt Plugins)。

使用 StyleKit 在 QML 中描述设计

StyleKit是一个声明式样式系统。样式是一个 QML 文件,其根对象为 `Style`,该对象为每种控件类型设置颜色、尺寸、半径、边框以及状态相关的变体。属性会沿控件层次结构传播,因此 `abstractButton ` 上设置一次的值将应用于所有类型的按钮,且一个样式可以定义多个命名主题。

QStyleKitStyle 是QStyle 的一个实现,它读取此类样式,并使用QPainter 绘制小部件。Qt Quick 不参与渲染过程。同一个Style 文件还为Qt Quick Controls 提供样式,因此同时使用这两个工具包的应用程序只需维护一个设计定义。样式中定义的主题可通过setThemeName()进行选择。

auto *style = new QStyleKitStyle(QStringLiteral(":/styles/MyStyle.qml"));
QApplication::setStyle(style);

QStyleKitStyle 该功能自 Qt 6.12 起提供。StyleKit 是 Qt Labs 模块,其 API 在不同 Qt 版本之间可能会发生变化。“StyleKit 控件示例”展示了一个包含多种 StyleKit 样式和主题的控件应用程序。

使用样式表进行原型设计

Qt 样式表通过类似 CSS 的语法规则来更改小部件的外观,无需编写 C++ 代码。它们非常适合用于设计尝试:编辑.qss 文件并重启应用程序,或者通过-stylesheet 命令行选项传递该文件, Qt Widgets Designer 即可预览这些规则的效果。这也是为单个控件(例如将必填字段设置为黄色背景)快速标记样式最快捷的方式。

样式表存在一些代价,使其不适合作为生产环境的样式设置机制:

  • 每个受影响的控件都会通过样式表引擎进行渲染。当设置样式表时,QWidget::style() 会返回一个样式表样式,该样式会包裹底层的style 。对于每个控件,它会根据控件的类、对象名、属性及状态匹配选择器,计算渲染规则,并按控件分别进行缓存。 内存和处理开销会随着控件数量和规则数量的增加而增长。
  • 更改样式表会重新渲染其所应用的所有内容。每次调用QApplication::setStyleSheet() 都会清空缓存并重新渲染应用程序中的每个控件,这会重新计算字体、配色方案、几何形状和尺寸提示,并可能导致可见的闪烁。请勿基于样式表构建主题切换功能。
  • 部分规则会舍弃原生外观。当某条规则要求原生样式无法满足的内容时(例如为QPushButton 设置背景色),样式表引擎会自行绘制整个元素,而不采用原生装饰。此时您必须自行指定边框、内边距以及所有状态,而一个微小的调整最终会演变成对外观的完整描述。 参见《使用样式表自定义Qt Widgets 》。
  • 选择器将设计与实现细节绑定在一起。规则会匹配类名、对象名和属性值。重命名对象或替换控件类,都会导致规则不再匹配,且不会产生任何提示。对于不依赖样式进行绘制的自定义控件,规则不会产生影响。
  • 样式表优于编程设置。样式表会覆盖通过QWidget::setFont()或QTreeWidgetItem::setBackground()等函数设置的字体、调色板和项目颜色,因此小部件的样式设置不再集中显示在一个地方。

有关样式表与QStyle 子类的并列比较,请参阅 KDAB 文章《拒绝 Qt 样式表》。

如果你还是想使用样式表

对于原型开发,或者生产应用程序所需的少量局部调整,请确保样式表易于管理:

  • 将规则保存在.qss 文件中,并将其打包到Qt资源系统中。在第一个窗口显示之前,通过QApplication::setStyleSheet()在应用程序中设置一次,并保持不变。将QWidget::setStyleSheet()保留用于真正仅针对某个控件及其子控件的局部调整。
  • 请勿使用 C++ 字符串来组装样式表。应用于小部件的样式表会针对每个应用该样式表的小部件进行一次解析,而非针对每个字符串进行一次解析;而且每次调用QWidget::setStyleSheet() 都会重新渲染该小部件及其所有子项,即使字符串内容未发生变化也是如此。 使用QString::arg() 构建的字符串(例如,用于表示无效值的红色边框)会随着每次更新而重新渲染控件。相反,应通过在单个样式表中使用对象名称或 Qt 属性的选择器来表达差异,并按照《使用动态属性进行自定义》中的说明进行重新评估。
  • 请勿硬编码颜色。诸如#ffffff 之类的字面颜色仅适用于一种主题。请使用palette(window) 、palette(text) 及其他调色板角色,确保样式表遵循应用程序调色板(包括深色配色方案)。
  • 请勿将所有尺寸单位都设为像素。 px 值会随显示器缩放,但不会随用户字体缩放。对于应随字体调整的内边距、外边距和尺寸,请使用em 和ex 长度单位;对于字体大小,请使用pt 。

从样式表过渡到样式

当原型转化为产品时,请将设计转移到样式中。大多数样式表结构都有直接对应的样式:

样式表QStyleStyleKit
颜色QPalette 角色,读取自QStyleOption::palette控件的颜色属性,或主题
border、padding 、marginpixelMetric() 和subElementRect()控件的边框和大小属性
伪状态,例如:hover 和:pressedQStyle::State 标志等QStyleOption::state状态组,例如hovered 和pressed
子控件,例如::indicatordrawPrimitive() 以及drawControl() 等子控件委托属性,例如indicator

另请参阅 “样式和支持样式的控件”、“QStyle ”、“QProxyStyle ”、“ QCommonStyle”、“Qt Labs StyleKit”以及“Qt 样式表”。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.