警告

本节包含自动从 C++ 转换为 Python 的代码段,可能包含错误。

样式和样式感知小部件#

样式和部件的样式。

样式(继承自 QStyle 的类)代表小部件进行绘制,并封装了 GUI 的外观和感觉。类 QStyle 是一个抽象基类,它封装了 GUI 的外观和感觉。Qt 内置的部件使用它来进行几乎所有的绘制,以确保它们看起来与等效的原生部件完全一样。

Qt 提供了一系列内置样式。某些样式仅在特定平台上可用。可以通过插件或使用 create() 创建特定样式类的实例并将其设置为 setStyle() 来提供自定义样式。

自定义样式#

为了自定义现有样式,需继承 QProxyStyle 并重新实现所需的虚拟方法。类 QProxyStyle 允许您指定特定的基本样式,或者当基本样式未指定时,它将自动使用应用程序样式。前者提供了对基本样式的完全控制,并在自定义需要特定样式行为时工作最佳,而后者提供了一种与平台无关的方式来定制默认为原生平台样式的应用程序样式。

实现自定义样式#

QCommonStyle 为完整的自定义样式实现提供了一个便捷的基类。其方法与 QProxyStyle 相同,但继承自 QCommonStyle 并重新实现了适当的虚函数。实现完整自定义样式相对复杂,因此我们提供了本概述。我们一步一步介绍了如何为单个 Qt 小部件设置样式。我们将研究 QStyle 的虚函数、成员变量和枚举。

本文档中不涉及单个小部件样式的部分应按顺序阅读,因为后面的部分往往依赖于前面的内容。在实现样式时,可以使用小部件的描述作为参考。然而,在某些情况下,您可能需要查阅 Qt 源代码。阅读本文档后,您可以清楚地了解样式过程的顺序,这将帮助您找到相关代码。

要开发样式感知小部件(即符合其绘制样式的样式小部件),您需要使用当前样式来绘制它们。本文档展示了小部件如何绘制自己以及样式提供了哪些可能性。

小部件样式类#

这些类用于自定义应用程序的外观和样式。

PySide6.QtWidgets.QGraphicsAnchorLayout

QGraphicsAnchorLayout 类提供了一个布局,其中可以在 Graphics View 中将小部件锚定在一起。

PySide6.QtWidgets.QGraphicsAnchor

QGraphicsAnchor 类代表在 QGraphicsAnchorLayout 中的两个项目之间的锚点。

PySide6.QtWidgets.QCommonStyle

QCommonStyle 类封装了 GUI 的通用外观和感觉。

The QPixmapStyle 类提供了基于位图的样式写入机制。

PySide6.QtWidgets.QStyle

QStyle 类是一个抽象基类,封装了 GUI 的外观和感觉。

PySide6.QtWidgets.QStyleFactory

QStyleFactory 类创建 QStyle 对象。

PySide6.QtWidgets.QStyleOption

QStyleOption 类存储了 QStyle 函数使用的参数。

PySide6.QtWidgets.QStyleHintReturn

QStyleHintReturn 类提供返回更多基本数据类型之外的风格提示。

PySide6.QtWidgets.QStyleHintReturnMask

QStyleHintReturnMask 类提供返回 QRegion 的风格提示。

PySide6.QtWidgets.QStyleHintReturnVariant

QStyleHintReturnVariant 类提供返回 QVariant 的风格提示。

PySide6.QtWidgets.QStylePainter

QStylePainter 类是一个方便类,用于在窗口内绘制 QStyle 元素。

The QWindowsStyle 类提供了类似 Microsoft Windows 的外观和感觉。

QStyle 实现方式#

QStyle 的 API 包含绘制小部件的函数、执行常见和困难任务的静态辅助函数(例如计算滑块手柄的位置)以及在绘制时所需的各个计算函数。样式还帮助某些小部件进行其内容的布局。此外,它创建一个包含用于绘制的 QBrush 的 QPalette。

QStyle 绘制图形元素;一个元素可以是小部件或小部件的一部分,例如推按钮斜面、窗口框架或滚动条。大多数绘制函数现在需要四个参数

  • 枚举值,指定要绘制哪个图形元素

  • QStyleOption,指定如何以及在哪里绘制该元素

  • 用于绘制元素的 QPainter

  • 绘图所在的小部件(可选)

当一个小部件请求样式绘制一个元素时,它为样式提供一个 QStyleOption,这是一个包含绘制所需信息的类。多亏了 QStyleOption,有可能在没有任何代码链接到小部件的情况下绘制小部件。这使得您可以在任何绘图设备上使用 QStyle 的绘制函数,即您可以在任何小部件上绘制组合框,而不仅仅是 QComboBox 上。

将小部件作为最后一个参数传递,以防样式需要它以执行特殊效果(如 macOS 上的动画默认按钮),但它不是必需的。

在本节的进程中,我们将查看样式元素、样式选项和 QStyle 的函数。最后,我们描述了调色板的使用方法。

项目视图中的条目通过 Qt 中的委托进行绘制。项目视图标题仍然由样式绘制。Qt 的默认委托 QStyledItemDelegate通过当前样式部分绘制其条目;它绘制复选框指示器并计算条目构成元素的边框矩形。在这份文档中,我们仅描述如何实现一个 QStyle 子类。如果您想为除了由QStyledItemDelegate支持的数据类型外添加支持,您需要实现一个自定义委托。请注意,委托必须针对每个单独的小部件进行程序化设置(即,默认委托不能作为插件提供)。

样式元素#

样式元素是GUI的图形部分。一个小部件由样式元素的层次结构(或树)组成。例如,当样式接收到绘制一个按钮(例如从QPushButton)的请求时,它会绘制一个标签(文字和图标)、一个按钮斜边和一个焦点框。按钮斜边由斜边周围的框架和另外两个元素组成,我们将稍后讨论。下面是按钮元素树的示意图。我们将在通过单个小部件时看到QPushButton的实际情况。

../_images/conceptualpushbuttontree.png

小部件不一定需要通过请求样式只绘制一个元素来绘制。小部件可以对样式进行多次调用以绘制不同的元素。一个例子是QTabWidget,它单独绘制其选项卡和框架。

有三个元素类型:基本元素、控件元素和复杂控件元素。这些元素由ComplexControlControlElementPrimitiveElement枚举定义。每个元素枚举的值都有一个前缀以标识其类型:CC_用于复杂元素,CE_用于控件元素,PE_用于基本元素。在以下三个部分中,我们将了解什么定义了不同的元素,并且将看到使用它们的窗口小部件的示例。

QStyle类描述包含这些元素及其在窗口小部件样式中的作用列表。我们将在样式单个窗口小部件时看到它们是如何使用的。

基本元素#

基本元素是常见的GUI元素,它们由多个小部件共同使用。这些元素的例子有框架、按钮斜边和用于微调框、滚动条和组合框的箭头。基本元素不能独立存在:它们始终是较大结构的一部分。它们不参与与用户的交互,但在GUI中是被动装饰。

控件元素#

控件元素执行操作或向用户显示信息。控件元素的例子有按钮、复选框以及表格和树视图中表头部分。控件元素不一定是完整的窗口小部件,如按钮,它们也可以是窗口小部件的部分,如选项卡栏选项卡和滚动条滑块。它们与基本元素的不同之处在于它们不是被动的,而是在与用户的交互中发挥作用。由多个元素组成的控件通常使用样式来计算元素的边界矩形。可用的子元素由SubElement枚举定义。此枚举仅用于计算边界矩形;子元素不是像基本元素、控件元素和复杂元素那样的图形元素。

复杂控件元素#

复杂的控件包含子控件。复杂控件的响应方式取决于用户用鼠标操作控件的哪个位置以及按下了哪个键盘键。这取决于鼠标是在哪个子控件(如果有)上或者在哪个子控件上按下。复杂控件的例子包括滚动条和组合框。使用滚动条,您可以使用鼠标来移动滑块并按下上箭头和下箭头按钮。可用的子控件通过 SubControl 枚举定义。

除了绘制之外,样式还需要向小部件提供关于在哪里按下鼠标的信息(如果有子控件)。例如,QScrollBar 需要知道用户是否按下了滑块、滑槽之一或按钮。

请注意,子控件不同于上一节中描述的控件元素。您不能使用样式来绘制子控件;样式只为子控件绘制应该绘制的边界矩形。然而,复杂的元素通常使用控件和原始元素来绘制子控件,这是 Qt 和 Java 风格内置样式中常用的一种方法。例如,Java 风格使用 PE_IndicatorCheckBox 来绘制组框中的复选框(它是 CC_GroupBox 的子控件)。某些子控件有等效的控件元素,例如滚动条滑块(SC_SCrollBarSliderCE_ScrollBarSlider)。

其他 QStyle 任务

如前所述,样式元素和小部件使用样式计算子元素和子控件的边界矩形。画面度量,是基于屏幕像素的样式相关大小,在绘制时也用于测量。可行的矩形和画面度量由 QStyle 中的三个枚举表示:SubElementSubControlPixelMetric . 枚举的值可以很容易地识别,因为它们以 SE_、SC_ 和 PM_ 开头。

样式还包含一组样式提示,这表示在 StyleHint 枚举中的值。所有小部件在不同的样式中都不具有相同的功能和外观。例如,当菜单项不能适应屏幕上的单列时,一些样式支持滚动,而其他样式则绘制多个列以适应所有项。

样式通常有一组标准图像(如警告、疑问和错误图像)用于消息框、文件对话框等。 QStyle 提供了 StandardPixmap 枚举。其值表示标准图像。Qt 的控件使用这些图像,因此当您实现自定义样式时,应提供所实现样式的图像。

样式计算布局中组件之间的间隔。样式处理这些计算的两种方式。你可以设置 PM_LayoutHorizontalSpacingPM_LayoutVerticalSpacing,这是Java样式的处理方式(通过 QCommonStyle)。或者,如果你需要更多对此布局部分的控制,可以实现 layoutSpacing() 以及 QStyle::layoutSpacingImplementation()。在这些函数中,你可以根据控件类型(ControlType)和不同大小策略(Policy)来计算间隔,也可以计算对应部件的样式选项。

样式选项#

QStyleOption 的子类包含用于风格的个性化组件所需的所有信息。样式选项通常在堆栈上实例化,并由 QStyle 函数的调用者填充。根据绘制的不同内容,样式会期望不同的样式选项类。例如,QStyle::PE_FrameFocusRect 元素期望 QStyleOptionFocusRect 参数,并可以创建自定义的子类,以供自定义样式使用。为了性能原因,样式选项保留了公开变量。

部件可以处于多种不同的状态,由 State 枚举定义。某些状态标志在部件间有不同的意义,但其他一些状态,例如 State_Disabled,对所有部件都相同。通过 QStyleOptioninitFrom() 方法设置常用状态;其余状态由各个部件单独设置。

最值得注意的是,样式选项包含要绘制的部件的调色板和边界矩形。大多数部件都有专门化的样式选项。例如,QPushButtonQCheckBox 使用它们自己的样式选项 QStyleOptionButton,该选项包含文本、图标以及图标的尺寸。在查看各个部件时将描述所有选项的确切内容。

在重新实现接受 QStyleOption 参数的 QStyle 函数时,通常需要将 QStyleOption 强制转换为子类(例如,QStyleOptionFocusRect)。为了安全起见,可以使用 qstyleoption_cast() 确保指针类型正确。如果对象类型不正确,qstyleoption_cast() 返回 None。例如

focusRectOption =
        QStyleOptionFocusRect(option)
if focusRectOption:
    ...

以下代码片段说明了如何使用 QStyle 在自定义小部件的 paintEvent() 方法中绘制焦点矩形

def paintEvent(self, event):

    painter = QPainter(self)
    ...
    option = QStyleOptionFocusRect(1)
    option.init(self)
    option.backgroundColor = palette().color(QPalette.Window)
    style().drawPrimitive(QStyle.PE_FrameFocusRect, option, painter,
                          self)

下一个示例显示了如何从现有样式派生以自定义图形元素的外观

class CustomStyle(QProxyStyle):

    Q_OBJECT
# public
    CustomStyle(QWidget widget)
    ~CustomStyle() {}
    def drawPrimitive(element, option,):
                       QPainter painter, QWidget widget) override

def drawPrimitive(self, element, option,):
                                QPainter painter, QWidget widget)

    if element == PE_IndicatorSpinUp or element == PE_IndicatorSpinDown:
        points = QPolygon(3)
        x = option.rect.x()
        y = option.rect.y()
        w = option.rect.width() / 2
        h = option.rect.height() / 2
        x += (option.rect.width() - w) / 2
        y += (option.rect.height() - h) / 2
        if element == PE_IndicatorSpinUp:
            points[0] = QPoint(x, y + h)
            points[1] = QPoint(x + w, y + h)
            points[2] = QPoint(x + w / 2, y)
        else: // PE_SpinBoxDown
            points[0] = QPoint(x, y)
            points[1] = QPoint(x + w, y)
            points[2] = QPoint(x + w / 2, y + h)

        if option.state  State_Enabled:
            painter.setPen(option.palette.mid().color())
            painter.setBrush(option.palette.buttonText())
        else:
            painter.setPen(option.palette.buttonText().color())
            painter.setBrush(option.palette.mid())

        painter.drawPolygon(points)
    else:
        QProxyStyle.drawPrimitive(element, option, painter, widget)

QStyle 函数#

QStyle 类为绘制基本、控件和复杂元素定义了三个函数:drawPrimitive()drawControl()drawComplexControl()。函数接受以下参数

  • 要绘制的元素的枚举值。

  • 一个 QStyleOption,其中包含绘制元素所需的信息。

  • 一个用于绘制元素的 QPainter。

  • 指向一个 QWidget 的指针,通常是绘制元素的窗口小部件。

并非所有小部件都会发送自己的指针。如果传递给函数的样式选项不包含您所需的信息,您应检查小部件实现以查看它是否发送了自己的指针。

QStyle 类还提供了一些辅助函数,这些函数在绘制元素时使用。函数 drawItemText() 在指定的矩形内绘制文本,参数为 QPalette。函数 drawItemPixmap() 帮助在指定的边界矩形内对齐位图。

其他 QStyle 函数为绘图函数执行各种计算。如果小部件自己绘制几个样式元素,它们也使用这些函数来计算尺寸提示和边界矩形。与绘图元素函数一样,辅助函数通常具有相同的参数。

  • 函数 subElementRect() 接收一个 SubElement 枚举值并计算子元素的边界矩形。样式使用此函数知道元素的不同部分应在何处绘制。这主要是为了复用;如果你创建一个新的样式,你可以使用与父类相同的子元素位置。

  • 函数 subControlRect() 用于计算复杂控件中子控件的边界矩形。当你实现一个新的样式时,你会重新实现 subControlRect() 并计算与父类不同的矩形。

  • 函数 pixelMetric() 返回一个像素度量值,它是在屏幕像素中给出的样式相关尺寸。它接收一个 PixelMetric 枚举值并返回正确的度量。请注意,像素度量不一定必须是静态度量,也可以使用,例如样式选项进行计算。

  • 函数 hitTestComplexControl() 返回在复杂数控件上鼠标指针所在的子控件。通常,这只是一些处理,使用 subControlRect() 获取子控件的边界矩形,然后查看哪个矩形包含鼠标的位置。

QStyle 还具有功能 polish()unpolish() 。所有小部件都在显示之前发送到 polish() 功能,并在它们隐藏时发送到 unpolish()。你可以使用这些功能在部件上设置属性或执行其他由你的样式要求的工作。例如,如果你需要知道鼠标是否悬停在部件上,你需要设置 WA_Hover 小部件属性。然后在部件的样式选项中设置 State_MouseOver 状态标志。

QStyle包含了几个静态辅助函数,用于执行一些常见且困难的任务。它们可以计算滑动条的滑块位置,并根据反向布局转换矩形和绘制文本;有关更多详细信息,请参阅QStyle类的文档。

实现QStyle虚函数的常用方法是对与超类不同的元素进行操作;对于所有其他元素,您可以直接使用超类的实现。

调色板#

每种样式都提供一套颜色调色板,即用于绘制小部件的QBrush调色板。它为不同的小部件状态(QPalette::ColorGroup)提供一套颜色:活动状态(具有键盘焦点的小部件)、非活动状态(用于其他窗口的小部件)和禁用状态(已禁用的小部件)。可以通过查询状态标志State_ActiveState_Enabled来找到状态。每个集合包含由QPalette::ColorRole枚举给出的某些颜色角色。角色描述了在哪些情况下应使用这些颜色(例如,用于绘制小部件背景、文本或按钮)。

颜色角色如何使用取决于样式。例如,如果样式使用渐变,则可以使用调色板颜色,并通过QColor::darker()和QColor::lighter()将其变暗或变亮以创建渐变。通常,如果需要不是由调色板提供的画笔,则应尝试从其中一个派生。

提供调色板的QPalette存储了不同小部件状态和颜色角色的颜色。样式的调色板通过standardPalette()返回。当在应用程序(setStyle())或小部件(setStyle())上设置新样式时,标准调色板不会自动安装,因此您必须自己使用(setPalette())或(setPalette())设置调色板。

不建议硬编码颜色,因为应用程序和单个小部件可以设置自己的调色板,并且还可以使用其样式的调色板进行绘制。请注意,Qt的所有小部件都不会设置自己的调色板。Java样式硬编码了一些颜色,但这仅是作者的决定;不建议这样做。当然,我们不希望样式在任何调色板上看起来都很好。

实现问题#

在实现样式时,有一些问题需要考虑。我们将在下面提供一些有关实现的提示和建议。

在实现样式时,有必要查看小部件及其基类及其祖先的代码。这是因为小部件使用的样式不同,因为不同样式的虚拟函数中的实现可能会影响绘制状态(例如,在不撤销的情况下更改 QPainter 状态并在未使用适当的像素度量及子元素的情况下绘制一些元素)。

建议不要使用 sizeFromContents() 函数更改小部件的预期大小,而让 QCommonStyle 实现来处理。如果需要更改,应尝试保持更改小;如果小部件的布局在不同的样式中看起来相差很大,则应用程序开发可能会很困难。

Java Style#

我们已经实现了一种类似于 Java 默认外观和感受(以前称为 Metal)的样式。我们这样做是因为它相对简单易行,并且我们希望为概述文档构建一个样式。为了使其简单且不过于广泛,我们对样式进行了某种简化,但 Qt 完全能够制作该样式的精确副本。但是,目前没有具体计划将其作为 Qt 的一部分进行实现。

在本节中,我们将探讨一些实现问题。最后,我们将看到一个关于 Java 小部件样式的完整示例。在整个文档中,我们将继续使用 Java 样式进行示例和 widgets 图像。实现本身有些复杂,并不打算让您阅读。

设计和实现#

设计样式的第一步是选择基类。我们选择从 QCommonStyle 继承。此类实现了我们所需要的大多数功能,除了执行实际绘制之外。

样式在单个类中实现。我们这样做是因为我们认为将所有代码保存在一个文件中很方便。此外,这有利于优化,因为我们实例化较少的对象。我们还通过使用开关来识别函数中要绘制哪个元素,将函数中的函数数量保持在最低水平。这会导致函数很大,但由于我们在开关中为每个元素划分代码,所以代码仍然应该易于阅读。

限制和与 Java 的差异#

我们并未完全实现 Java 样式中的每个元素。这样,我们减少了代码量和复杂性。总的来说,该样式是作为本样式概述文档的实用示例,而不作为 Qt 本身的一部分。

并非所有小部件都实现了每种状态。这适用于常见的状态,例如 State_Disabled。但是,每种状态至少为一个小部件实现了。

我们在滑块下方仅实现了刻度。平面按钮也省略了。我们不处理标题栏和停靠窗口标题因内容太小而变得过小的情况,而是简单地重叠绘制子控件。

我们没有尝试模拟 Java 字体。Java 和 Qt 使用非常不同的字体引擎,所以我们不认为这在作为本概述示例的情况下值得努力。

我们为线性渐变硬编码了颜色(我们不使用QPalette),这些渐变应用于按钮斜边、工具栏和复选框等。这是因为Java调色板无法产生这些颜色。无论如何,Java不会根据小部件颜色组或角色更改这些颜色(它们不依赖于调色板),因此在任何情况下都不会引起问题。

Qt的小部件进行了样式化。一些Java中根本不存在的小部件,例如QToolBox。其他小部件包含Java小部件不具备的元素。树小部件是一个例子,Java的JTree没有表头。

样式不处理反向布局。我们假设布局方向是左到右。QCommonStyle处理反向小部件;如果我们实现了反向布局,则需要更新改变子元素位置或自行处理标签文本对齐的小部件。

Java复选框的样式

作为一个例子,我们将检查Java样式中复选框的样式。我们将描述完整的流程并打印出Java样式和Qt类中的所有代码。在本文档的其余部分,我们将不检查单个小部件的源代码。希望这能让你对如何检查特定实现细节有一个想法;大多数小部件的结构都与复选框相同。我们对QCommonStyle代码进行了一些编辑,以删除与复选框样式不直接相关的代码。

我们从查看QCheckBox如何构建其样式选项开始,该选项为复选框QStyleOptionButton

    opt.initFrom(q)
        if down:
        opt.state |= QStyle.State_Sunken
    if tristate and noChange:
        opt.state |= QStyle.State_NoChange
else:
        opt.state |= checked ? QStyle.State_On :
        QStyle.State_Off
    if q.testAttribute(Qt.WA_Hover) and q.underMouse():
        if hovering:
        opt.state |= QStyle.State_MouseOver
else:
        opt.state = ~QStyle.State_MouseOver

    opt.text = text
    opt.icon = icon
    opt.iconSize = q.iconSize()

首先,我们使用initFrom()QStyleOption设置公共信息的选项。我们很快就会查看这一点。

QStyleOptiondown 变量在用户按下复选框时为 true;无论复选框是否勾选,都适用于此。当三态复选框部分勾选时,设置 State_NoChange 状态。如果复选框被勾选,则为 State_On,如果未勾选,则为 State_Off。当鼠标悬停在复选框上且小部件具有属性 Qt::WA_Hover 并在 polish() 中设置时,会设置 State_MouseOver。此外,样式选项还包括按钮的文本、图标和图标大小。

initFrom() 使用适用于所有小部件的通用属性设置样式选项。我们在此打印其实现。

    state = QStyle.State_None
    if widget.isEnabled():
        state |= QStyle.State_Enabled
    if widget.hasFocus():
        state |= QStyle.State_HasFocus
    if widget.window().testAttribute(Qt.WA_KeyboardFocusChange):
        state |= QStyle.State_KeyboardFocusChange
    if widget.underMouse():
        state |= QStyle.State_MouseOver
    if widget.window().isActiveWindow():
        state |= QStyle.State_Active
#ifdef QT_KEYPAD_NAVIGATION
    if widget.hasEditFocus():
        state |= QStyle.State_HasEditFocus
#endif
    direction = widget.layoutDirection()
    rect = widget.rect()
    palette = widget.palette()
    fontMetrics = widget.fontMetrics()

当小部件启用时,设置 State_Enabled。当小部件获得焦点时,设置 State_HasFocus 标志。同样,当小部件是活动窗口的子窗口时,设置 State_Active 标志。《State_MouseOver 将仅在具有 WA_HoverEnabled 窗口标志的小部件上设置。注意,在 Qt 中必须启用键盘导航才能将 State_HasEditFocus 包含在内;默认情况下不会包含。

除了设置状态标志之外,QStyleOption 还包含有关小部件的其他信息:direction 是布局的方向,rect 是小部件的边界矩形(绘制区域),palette 是绘制小部件时应使用的 QPalette,而 fontMetrics 是小部件使用的字体度量。

我们提供了一个复选框的图片和对应的样式选项。

../_images/checkboxexample.png

上述复选框在其样式选项中将具有以下状态标志。

状态标志

设置

State_Sunken

State_NoChange

State_On

State_Off

State_MouseOver

State_Enabled

State_HasFocus

State_KeyboardFocusChange

State_Active

QCheckBox 组件在 paintEvent() 事件中,使用样式选项 optQStylePainter 类来绘制自己。QStylePainter 类是一个方便的类,用于绘制样式元素。最值得注意的是,它封装了用于绘画的 QStyle 中的方法。QCheckBox 组件的绘制过程如下

p = QStylePainter(self)
opt = d.getStyleOption()
p.drawControl(QStyle.CE_CheckBox, opt)

QCommonStyle 处理 CE_CheckBox 元素。QCheckBox 有两个子元素:SE_CheckBoxIndicator(复选框的选中指示器)和 SE_CheckBoxContents(内容,用于复选框标签)。QCommonStyle 还实现了这些子元素的边界矩形。接下来,我们将查看 QCommonStyle 的代码

subopt = btn
subopt.rect = subElementRect(SE_CheckBoxIndicator, btn, widget)
drawPrimitive(PE_IndicatorCheckBox, subopt, p, widget)
subopt.rect = subElementRect(SE_CheckBoxContents, btn, widget)
drawControl(CE_CheckBoxLabel, subopt, p, widget)
if btn.state  State_HasFocus:
    fropt = QStyleOptionFocusRect()
    fropt.QStyleOption.operator=(btn)
    fropt.rect = subElementRect(SE_CheckBoxFocusRect, btn, widget)
    drawPrimitive(PE_FrameFocusRect, fropt, p, widget)

从代码片段中可以看出,通用样式获得 CE_CheckBox 两个子元素的边界矩形,然后绘制它们。如果复选框具有焦点,则也会绘制焦点框架。

Java 样式绘制 CE_CheckBoxIndicator,而 QCommonStyle 则处理 CE_CheckboxLabel。我们将检查每个实现,并从 CE_CheckBoxLabel 开始

    btn = QStyleOptionButton(opt)
    alignment = visualAlignment(btn.direction, Qt.AlignLeft | Qt.AlignVCenter)
    if not styleHint(SH_UnderlineShortcut, btn, widget):
        alignment |= Qt.TextHideMnemonic
    pix = QPixmap()
    textRect = btn.rect
    if not btn.icon.isNull():
        pix = btn.icon.pixmap(btn.iconSize, btn.state  State_Enabled if QIcon.Normal else QIcon.Disabled)
        drawItemPixmap(p, btn.rect, alignment, pix)
        if btn.direction == Qt.RightToLeft:
            textRect.setRight(textRect.right() - btn.iconSize.width() - 4)
else:
            textRect.setLeft(textRect.left() + btn.iconSize.width() + 4)

    if not btn.text.isEmpty():
        drawItemText(p, textRect, alignment | Qt.TextShowMnemonic,
            btn.palette, btn.state  State_Enabled, btn.text, QPalette.WindowText)

visualAlignment() 方法根据布局方向调整文本的对齐方式。如果存在图标,则绘制图标,并调整文本的剩余空间。drawItemText() 根据对齐方式、布局方向和快捷键绘制文本。它还使用调色板以正确颜色绘制文本。

标签的绘制通常比较复杂。幸运的是,它通常可以通过基类来处理。《Java》样式的实现有自己的按钮标签,因为当按钮具有图标时,Java 也使按钮内容居中。如果您需要重新实现标签绘制的示例,可以查看该实现的示例。

现在,我们将查看在 drawControl() 中实现的 Java 对 CE_CheckBoxIndicator 的实现

elif flag == PE_IndicatorCheckBox:
    painter.save()
    drawButtonBackground(option, painter, True)
    if (option.state  State_Enabled and
        option.state  State_MouseOver and
        not (option.state  State_Sunken)) {
        painter.setPen(option.palette.color(QPalette.Button))
        rect = option.rect.adjusted(1, 1, -2, -2)
        painter.drawRect(rect)
        rect = rect.adjusted(1, 1, -1, -1)
        painter.drawRect(rect)

    if option.state  State_On:
        image = QImage(":/images/checkboxchecked.png")
        painter.drawImage(option.rect.topLeft(), image)

    painter.restore()
    break

首先保存绘图器的状态。这并不总是必要的,但在这种情况下,QCommonStyle 需要绘图器的状态与调用 PE_IndicatorCheckBox 时的状态相同(当然,我们也可以通过函数调用设置状态)。然后我们使用 drawButtonBackground() 来绘制复选框指示器的背景。这是一个辅助函数,它绘制背景以及单选按钮和复选框的框架。我们下面会看一下这个函数。然后我们检查鼠标是否悬停在复选框上。如果是,我们绘制 Java 复选框在没有按下且鼠标悬停时的框架。你可能注意到 Java 不处理三态框,所以我们没有实现它。

在这里,我们使用 PNG 图像作为指示器。我们也可以检查小部件是否被禁用。如果是,我们则需要使用具有指示器禁用颜色的另一张图像。

def drawButtonBackground(self, option,):
                                     QPainter painter, bool isCheckbox)

    buttonBrush = option.palette.button()
    sunken = option.state  State_Sunken
    disabled = not (option.state  State_Enabled)
    on = option.state  State_On
    if not sunken and not disabled and (not on or isCheckbox):
        buttonBrush = gradientBrush(option.rect)
        painter.fillRect(option.rect, buttonBrush)
        rect = option.rect.adjusted(0, 0, -1, -1)
        if disabled:
            painter.setPen(option.palette.color(QPalette.Disabled,
                                                  QPalette.WindowText))
else:
            painter.setPen(option.palette.color(QPalette.Mid))
        painter.drawRect(rect)
        if sunken and not disabled:
            drawSunkenButtonShadow(painter, rect,
                   option.palette.color(QPalette.Mid),
                   option.direction == Qt.RightToLeft)

我们已经看到了复选框在 Java 风格下的样式是如何从小部件收到绘制请求开始到完成样式绘制的过程中进行样式的。要详细了解每个小部件是如何绘制的,你需要逐步通过代码,就像我们在这里做的那样。然而,通常只需知道小部件绘制的样式元素就足够了。小部件构建一个样式选项,并调用样式一或多次来绘制它由哪些样式元素组成。通常,了解小部件可以处于哪些状态以及样式选项的其他内容(即下一节列出的内容)也就足够了。

小部件遍历#

在本节中,我们将检查大多数 Qt 小部件的样式。希望这能让你在开发自己的样式和小部件时节省一些时间和精力。这里的信息不是其他地方得不到的(即通过检查源代码或与样式相关的类描述)。

我们主要使用 Java 风格小部件作为示例。Java 风格不绘制元素树中的每个元素。这是因为它们在 Java 风格中对那个小部件是不可见的。我们仍然确保所有元素都是以符合 Java 风格的方式实现的,因为自定义小部件可能需要它们(这并不排除将实现留给 QCommonStyle)。

以下是对每个小部件的说明

  • 包含其样式选项成员(变量等)的表。

  • 可以设置在控件上的状态标志( StateFlag )及其设置状态的表。

  • 它的元素树(参见样式元素部分)。

  • 突出显示元素的控件图像。

元素树包含原始、控件和复杂样式元素。通过对元素树自顶向下的遍历,你得到元素应该绘制的顺序。在节点中,我们已经写出了应考虑绘制节点元素的子元素矩形、子控件和像素度量。

我们的样式方法主要集中在小部件的绘制上。在绘制过程中使用的子元素矩形、子控制和像素度量只作为元素树中的内容列出。注意,有些矩形和像素度量仅供小部件使用。这导致这些计算在演示中未进行处理。例如,subControlRect()sizeFromContents() 函数通常调用 subElementRect() 来计算其边界矩形。我们也可以为这些绘制树。然而,这些计算的执行方式完全取决于个别样式,而且它们不必遵循特定的结构(Qt 不强制规定特定结构)。但是,您仍应确保使用适当的像素度量。为了限制文档的大小,我们因此选择不包括树或描述 Java(或任何其他)样式的计算。

您在检查树的时候可能会对如何使用不同的像素度量、子元素矩形和子控制矩形感到困惑。如果阅读了QStyle 枚举描述后仍然不确定,我们建议您检查 QCommonStyle 的实现。

我们没有显示在部件图像中的某些边界矩形是相同的。原因是某些元素绘制背景,而其他元素则绘制边框和标签。如有疑问,请检查QStyle 中每个元素的描述。此外,某些元素用于布局,即决定绘制其他元素的位置。

常见部件属性#

某些状态和变量所有部件都有。这些是通过 initFrom() 设置的。并非所有元素都使用此函数;创建样式选项的是部件,对于某些元素,initFrom() 中的信息不是必需的。

下表列举了共同的状态

状态

状态设置条件

State_Enabled

如果小部件未禁用(见 setEnabled() )则设置

状态_Focus

如果小部件具有焦点(见 hasFocus() )则设置

State_KeyboardFocusChange

当用户用键盘改变焦点(见 Qt::WA_KeyboardFocusChange)时设置

State_MouseOver

如果鼠标光标在小部件上则设置

State_Active

如果小部件是活动窗口的子窗口则设置

状态_HasEditFocus

如果小部件具有编辑焦点则设置

小部件的常见成员包括

成员

内容

rect

要绘制的元素的边界矩形。这个设置为小部件的边界矩形(rect())。

direction

布局方向;Qt::LayoutDirection枚举的值。

palette

使用该画布绘制元素时要使用的QPalette。这个设置为小部件的画布(palette())。

fontMetrics

绘制小部件上文本时要使用的QFontMetrics。

用于复杂样式元素的复杂样式选项(继承自QStyleOptionComplex的类)共享两个变量:subControlsactiveSubControls。这两个变量都是SubControl枚举值的“或”组合。它们指示复杂控件包含哪些子控件,以及哪些控件当前是活动的。

如前所述,样式计算小部件内容的尺寸,小部件根据这些尺寸提示计算大小。此外,复杂控件也使用样式来测试鼠标是否位于子控件上。

小部件参考#

无需拖延,我们将展示小部件的遍历;每个小部件都有自己的子部分。

推按钮#

下表显示了推按钮的样式结构。通过从上至下遍历树,您可以获取元素的绘制顺序。

../_images/pushbutton.png

按键的布局,就元素边界而言,因样式而异。这使展示这种概念图像变得困难。此外,元素可能(甚至有意)具有相同的边界;例如,在PE_PushButtonBevel中使用的,它在QCommonStyle中用于绘制其包含的元素:PE_FrameDefaultButtonPE_FrameButtonBevelPE_PanelButtonCommand,这些都在常规样式中具有相同的边界。PE_PushButtonBevel还负责绘制菜单指示器(QCommonStyle绘制PE_IndicatorArrowDown)。

以下是一个按Java样式绘制的推按钮图像,显示了元素的边界矩形。颜色用于在图像中分隔边界矩形;它们没有其他用途。对于其他小部件的类似图像也是如此。

../_images/button.png

Java样式以及Qt中实现的所有其他样式都不使用PE_FrameButtonBevel。通常,具有PE_DefaultFrame的按钮通过PM_ButtonDefaultIndicator调整PE_PanelButtonCommand的矩形。通过PM_DefaultFrameWidth调整矩形可找到CE_PushButtonLabel

我们现在将检查按钮样式的选项 - QStyleOptionButton。以下是一个表格,展示了QPushButton可以在样式选项中设置的各个状态

状态

状态设置条件

State_Sunken

按钮按下或菜单项被点击时显示

State_On

按钮处于选中状态

State_Raised

按钮不是平坦的且没有被按下

QStyleOptionButton的其他成员包括

成员

内容

功能

ButtonFeatures枚举的标志位,描述了按钮的各种属性(见枚举)

图标

按钮的QIcon(如果有)

图标大小

图标的QSize

文本

按钮的QString文本

复选框和单选按钮#

单选按钮和复选按钮的结构是相同的。我们使用QCheckBox元素和像素度量名称来展示结构

../_images/checkbox.png

QStyleOptionButton用作复选框和单选按钮的样式选项。我们首先提供一个表格,列出可以在选项中设置的各个状态

状态

状态设置条件

State_sunken

框被按下

State_NoChange

框被部分选中(用于三态复选框)

State_On

框被选中

State_Off

框被取消选中

有关QStyleOptionButton中其他成员的表格,请参阅弹出按钮

标签页#

在Qt中,QTabBar使用样式来绘制其标签页。标签页存在于一个QTabWidget中,该窗口包含一个QTabBar,或者作为一个单独的条。如果该条不是 tab 窗口的一部分,它将绘制自己的基

QTabBar布局标签页,因此样式不控制标签的位置。然而,在布局标签页时,条要求样式提供PM_TabBarTabHSpacePM_TabBarTabVSpace,这是标签页条标签(图标和文本)最小尺寸之外的额外宽度和高度。样式还可以在布局之前进一步影响标签的大小,因为标签页要求CT_TabBarTab。当条是窗口的一部分时,条的外包围矩形由 tab 窗口决定(仍然考虑CT_TabBarTab)。

标签栏负责绘制当所有标签无法适应时出现的按钮。其位置不由样式控制,但按钮是由 QToolButton 绘制的,因此由样式决定。

以下是 QTabWidgetQTabBar 的样式结构

../_images/tab.png

虚线表示 QTabWidget 包含标签栏,但并不绘制标签栏本身。 QTabBar 只有在不属于标签控件时才绘制其基线;当所有标签不适应时,它保持了两个滚动条的工具按钮;见 Tool Buttons 了解它们的元素树。请注意,按钮是标签栏的子代,因此它们在标签栏之后绘制。标签的边界矩形与基线的重叠由 PM_TabBarBaseOverlap 确定。

以下是 Java 风格的标签控件

../_images/tabwidget.png

在 Java 风格中,标签栏的形状和标签具有与 CE_TabBarTab 相同的边界矩形。注意标签与标签控件框架重叠。标签栏的底部(如果绘制)是标签和框架重叠的区域。

标签的样式选项( QStyleOptionTab )包含绘制标签所需的信息。该选项包含标签在标签栏中的位置,选中标签的位置,标签的形状,文本,图标和图标的大小。

由于 Java 风格的标签不重叠,我们我们还提供了一个常见样式的标签控件的图像。请注意,如果您想要水平重叠标签,则在 CE_TabBarTabShape 绘制标签时执行;标签的边界矩形不会被标签栏更改。标签从左到右在北标签栏形状中绘制,从上到下在东标签栏形状中绘制等。选中的标签最后绘制,以便它易于绘制在其他标签之上(如果它要更大)。

../_images/windowstabimage.png

以下表格列出标签栏可以对其标签设置的各个状态

状态

状态设置条件

State_Sunken

用鼠标按下标签。

State_Selected

如果它是当前标签。

State_HasFocus

标签栏有焦点且标签被选中。

请注意,即使标签栏不可用,单个标签也可能被禁用。如果标签栏处于活动状态,则标签将是活跃的。

以下是 QStyleOptionTab 成员的表格

成员

内容

cornerWidgets

CornerWidget 枚举的标志,指示标签栏是否有以及哪些角控件。

图标

标签的 QIcon。

图标大小

图标的 QSize。

position

指示标签在条杠上的位置相对于其他标签的 TabPosition 枚举值。

row

指示标签所在的行。

selectedPosition

SelectedPosition 枚举类型的值,表示所选标签是否与标签相邻或即为此标签。

形状

表示标签的角落是圆角还是三角形以及标签方向的 Shape 枚举类型的值。

文本

标签文本。

标签小部件使用的框架为 QStyleOptionTabWidgetFrame 作为样式选项。我们在这里列出其成员。除了公共标志外,没有设置状态。

成员

内容

左角部件大小

左角部件的 QSize(如果有)。

右角部件大小

右角部件的 QSize(如果有)。

行宽

用于绘制面板的行宽。

中线路径

此值当前始终为 0。

形状

选项卡工具条上标签的形状。

标签工具条大小

标签工具条的 QSize。

滚动条#

以下是滚动条的样式结构

../_images/scrollbar.png

QScrollBar 简单地创建其样式选项,然后绘制 CC_ScrollBar。某些样式使用 PE_PanelButtonBevel 绘制添加和删除页面的背景,并使用指示箭头绘制前一行和下一行的箭头;我们没有将这些包括在树中,因为它们的使用取决于个人样式。样式的 PM_MaximumDragDistance 是鼠标可以从滚动条界限移动的最远距离(以像素为单位)并仍然可以移动滑块。

以下是 Java 样式滚动条的图片

../_images/scrollbarimage.png

您可能会注意到,滚动条与 Java 的略有不同,因为它有两个向上指示器。我们这样做是为了表明您可以为单个子控件设置两个不同的边界矩形。滚动条是 Java 样式的完全实现的示例 - QCommonStyle 没有参与绘制。

我们将查看滚动条可以在样式选项上设置的不同状态

状态

状态设置条件

State_Horizontal

滚动条是水平方向的。

QScrollBar 的样式选项是 QStyleOptionSlider。其成员列在下面的表中。该选项由所有 QAbstractSlider 使用;我们只描述与滚动条相关的成员。

成员

内容

最大值

滚动条的最大值。

最小值

滚动条的最小值。

刻度目标

刻度之间的像素数。

方向

指定滚动条是垂直还是水平的 Qt::Orientation 枚举类型的值。

页面步长

用于在页面步骤中增加或减少滑块值(相对于滑块大小和它的值范围)的数字。

singleStep

用于在单一(或线性)步骤中增加或减少滑块值的数字。

sliderValue

滑块的值。

sliderPosition

滑块手柄的位置。如果滚动条是 tracking ,则这和 sliderValue 相同。如果不是,则在鼠标释放手柄之前,滚动条不会更新其值。

upsideDown

保存滚动条增加值的方向。对于所有抽象滑块,使用此选项代替 QStyleOption::direction

滑块#

在计算滑块大小提示时,从样式查询 PM_SliderThicknessPM_SliderLength。与滚动条一样,QSlider 只允许用户移动手柄,当鼠标在滑块边界内 PM_MaximumDragDistance 的距离内时。当它自己绘制时,它创建样式选项并使用 CC_Slider 调用 drawComplexControl()

../_images/slider.png

我们还展示了Java样式的滑片图片。我们展示了子元素的边界矩形,因为所有的绘制都是在 CC_Slider 中完成的。

../_images/sliderimage.png

QSlider 使用 QStyleOptionSlider ,就像所有的 QAbstractSlider 一样。我们提供了一个表格,其中包含影响 QSlider 的成员。

成员

内容

最大值

滑块的最大值。

最小值

滑块的最小值。

刻度目标

这是每个刻度之间的像素数。

方向

一个 Qt::Orientation 枚举值,指示滑块是垂直还是水平。

页面步长

用于在页面步骤中增加或减少滑块值的数字。

singleStep

用于在单一(或线性)步骤中增加或减少滑块值的数字。

sliderValue

滑块的值。

sliderPosition

给定滑块值的滑块位置。如果滑块是 tracking ,则这将等于 sliderValue;如果不是,则在释放鼠标之前,滑块的值不会改变。

upsideDown

对于所有抽象滑块,使用此成员代替 QStyleOption::direction

请注意,滑块不使用方向进行反向布局;它使用 upsideDown

数字框#

QSpinBox绘制自身时,它会创建一个QStyleOptionSpinBox并让样式引擎绘制CC_SpinBox。编辑字段是一个子类于滚动条的行编辑控件。该字段的尺寸由样式引擎使用SC_SpinBoxEditField计算。

下面是滚动条的样式树。不要求样式使用按钮面板原语来绘制指示器背景。您可以在下方的图片中看到,Java样式中QSpinBox的子元素。

../_images/spinbox.png ../_images/spinboximage.png

QStyleOptionSpinBox,它是滚动条样式的选项。它可以设置以下滚动条的状态

状态

状态设置条件

State_Sunken

如果按下鼠标时按下子控件CC_SpinUpCC_SpinDown之一,则为设置。

滚动条样式选项的其他成员包括

属性

函数

框架

一个布尔值,当其为true时,表明滚动条将绘制一个框架。

按钮符号

用于确定上下按钮上符号的ButtonSymbols枚举值。

步进启用

StepEnabled枚举的值,指示哪个滚动条按钮被按下。

标题栏

标题栏复杂控件CC_TitleBar用于绘制QMdiArea内部的窗口的标题栏。它通常由窗口标题以及关闭、最小化、系统菜单和最大按钮组成。一些样式还提供了用于窗口阴影以及与上下文相关的帮助按钮。

此条在CC_TitleBar中绘制,而不使用任何子元素。各个样式如何绘制它们自己的按钮由它们自己决定,但样式应该提供按钮的标准位图。

../_images/titlebar.png

在Java样式的标题栏上面的图像中,我们显示了Java样式支持的子元素的支持边框矩形(所有这些均使用标准位图绘制)。通常使用PE_PanelButtonTool绘制按钮背景,但这不是必需的。

../_images/titlebarimage.png

标题栏的样式选项为QStyleOptionTitleBar。它的成员包括

成员

内容

图标

标题栏的图标。

文本

标题栏标签的文本。

窗口标志

Qt::WindowFlag枚举的标志。它由QMdiArea用于窗口管理。

标题栏状态

这是包含标题栏的窗口的 windowState() 方法。

组合框#

一个 QComboBox 使用 CC_ComboBoxCE_ComboBoxLabel 风格绘制不可编辑框的按钮和标签。

用户点击组合框时弹出的列表由一个 代理 绘制,本文档概述中不涉及该部分。但是,您可以使用子元素 SC_ComboBoxListBoxPopup 控制列表的大小和位置。风格还决定可编辑框的编辑字段在哪里,使用 SC_ComboBoxEditField;字段本身是组合框的一个 QLineEdit 子组件。

../_images/combobox.png

我们展示了在一个Java风格的组合框上方的图片,我们已勾勒出其子元素和子元素矩形。

../_images/comboboximage.png

Java组合框不使用焦点矩形;当它有焦点时,它会更改其背景颜色。字段 SC_ComboBoxEdit 同时由 QComboBox 用于计算编辑字段的大小和组合框标签的样式。

组合框的样式选项是 QStyleOptionComboBox 。它可以设置以下状态

状态

设置条件

State_Selected

当组合框不可编辑且具有焦点时。

State_Sunken

SC_ComboBoxArrow 是激活的。

状态_开

组合框(列表)的容器是可见的。

其他样式选项成员包括

成员

内容

currentIcon

组合框当前(选中)项的图标。

currentText

组合框当前项的文本。

editable

表示组合框是否可编辑。

框架

表示组合框是否有框架。

图标大小

当前项图标的尺寸。

popupRect

组合框弹出列表的边界矩形。

分组框#

在计算大小提示时,QGroupBox 从样式中提取三个像素度量: PM_IndicatorWidthPM_CheckBoxLabelSpacingPM_IndicatorHeightQGroupBox 有以下样式元素树

../_images/groupbox.png

Qt 对复选框的绘制方式没有强制要求;Java 风格使用 CE_IndicatorCheckBox 绘制。请参阅 复选框和单选按钮 的完整列表。

我们还提供了一张带有子控件和子控件矩形的控件图片

../_images/groupboximage.png

组框的样式选项是 QStyleOptionGroupBox 。以下可以设置的状态有

状态

设置条件

State_On

复选框被勾选。

State_Sunken

复选框被按下。

State_Off

复选框未被勾选(或没有复选框)。

QStyleOptionGroupBox 的其余成员包括

成员

内容

功能

FrameFeatures 枚举的标志,描述了组框的框架。

行宽

绘制面板时要用的线条宽度。这始终是 1。

文本

组框的文本。

textAlignment

组框标题的对齐方式。

textColor

文本的 QColor。

分隔符#

由于分隔符的结构很简单,并且不包含任何子元素,我们不包括任何分隔符的图片。 CE_Splitter 不使用任何其他元素或度量。

对于样式选项,分隔符使用基类 QStyleOption 。它可以设置以下状态标志

状态

设置条件

State_Horizontal

如果是水平分隔符。

QSplitter 不使用 initFrom() 来设置其选项;它自己设置了 State_MouseOverState_Disabled 标志。

进度条#

元素 CE_ProgressBarQProgressBar 使用,并且它是此小部件使用的唯一元素。我们以样式结构开始

../_images/progressbar.png

这是一个通用样式(Java 风格的边界矩形相等)的进度条

../_images/progressbarimage.png

QProgressBar 的样式选项是 QStyleOptionProgressBar 。该进度条不设置任何状态标志,但选项的其他成员是

成员

内容

最小值

进度条的最小值。

最大值

进度条的最大值。

progress

进度条的当前值。

textAlignment

在标签中的文本对齐方式。

textVisible

标签是否绘制。

文本

标签文本。

方向

进度条可以是垂直的或水平的。

invertedAppearance

进度显示是反转的(即水平条从右到左显示)。

从下到上

布尔值,如果设置为 true,则将垂直进度条的标签旋转90度。

工具按钮#

工具按钮可以独立存在,也可以作为工具栏的一部分。无论是哪种方式绘制,它们的外观都是相同的。在 QToolButton 中,只绘制一种样式元素:CC_ToolButton

以下是小部件样式结构的树结构

../_images/toolbutton.png

请注意,PE_FrameButtonToolPE_IndicatorArrowDown 已包含在树中,因为Java样式会那样绘制它们,但如果您愿意,可以安全地省略。结构也可能不同。例如,QCommonStyle 会同时将 PE_IndicatorButtonDropDownPE_IndicatorArrowDown 绘制在 CE_ToolButton 中。

以下是一个工具按钮的图像,其中我们标出了子元素边界矩形和子控件。

../_images/toolbuttonimage.png

以下是工具按钮的状态表

状态

设置条件

自动升起

工具按钮的自动升起属性已被设置。

State_Raised

按钮未被压下(即未被选中或用鼠标按下)。

State_Sunken

按钮处于按下状态。

State_On

按钮可勾选且已勾选。

QStyleOptionToolButton 还包含以下成员

成员

内容

箭头类型

Qt::ArrowType 枚举值,包含按钮箭头的方向(如果要用箭头代替图标)。

功能

描述按钮是否有箭头、菜单以及/或有弹出延迟的 QStyleOptionToolButton::ButtonFeature 枚举标志。

字体

按钮标签的 QFont。

图标

工具按钮的 QIcon。

图标大小

按钮图标的尺寸。

位置

按钮的位置,如由 pos() 定义。

文本

按钮的文本。

工具按钮样式

Qt::ToolButtonStyle 枚举值,决定按钮是否显示图标、文本或两者都显示。

工具栏#

工具栏是 主窗口框架 的一部分,并在构建其样式选项时与它们所属的 QMainWindow 合作。主窗口有4个区域,工具栏可以放置在其中。它们位于窗口的四个侧面(即北、南、东和西)。在每个区域内可以有多个工具栏行;一行是一系列具有相同方向的工具栏(垂直或水平)并列放置。

Qt中的工具栏包含三个元素:CE_ToolBarPE_IndicatorToolBarHandlePE_IndicatorToolBarSeparator。是 QMainWindowLayout 计算了工具栏及其内容的边界矩形(即位置和大小)。主窗口在计算工具栏的大小时会使用工具栏内元素的 sizeHint()

以下是 QToolBar 的元素树

../_images/toolbar.png

虚线表示 QToolBar 保持 QToolBarLayout 的一个实例,而 QToolBarSeparators 由 QToolBarLayout 维护。当工具栏浮动(即,有独立的窗口)时,将绘制 PE_FrameMenu 元素,否则 QToolBar 绘制 CE_ToolBar

以下是带有 Java 样式的工具栏的图片

../_images/toolbarimage.png

QToolBarSeparator 使用 QStyleOption 的样式选项。如果它所在的工具栏是横向的,则设置 State_Horizontal 标志。除此之外,它们使用 initFrom()

QToolBar 的样式选项是 QStyleOptionToolBar。除了公共标志外,唯一设置的标志是当工具栏是横向的(即,在北或南工具栏区域)时的 State_Horizontal。样式选项的成员变量包括

成员

内容

功能

在 ToolBarFeature 的值中保持工具栏是否可移动,它可以是 Movable 或 None。

行宽

工具栏框架的宽度。

midLineWidth

该变量目前未使用,始终为 0。

positionOfLine

线属于的工具栏区内的工具栏线位置。

positionWithinLine

工具栏在线内的位置。

toolBarArea

工具栏所在的工具栏区域。

项目视图标题#

这是绘制 Qt 项目视图标题的样式。项目视图会保持单个部分的尺寸。此外,委托可以使用样式来绘制项目周围的装饰和框架。例如,QItemDelegate 会绘制 PE_FrameFocusRectPE_IndicatorItemViewItemCheck

../_images/header.png

以下是一个显示 Java 头部边界矩形的 QTableWidget 示例

../_images/headerimage.png

QHeaderView 使用 CT_HeaderSectionPM_HeaderMarginPM_HeaderGripMargin 进行尺寸和点击测试计算。当前 Qt 不使用 PM_HeaderMarkSizeQTableView 将按钮(即垂直和水平标题交汇的区域)绘制为 CE_Header

标题视图的样式选项是 QStyleOptionHeader 。视图一次绘制一个标题部分,因此数据是关于正在绘制的部分。内容如下:

成员

内容

图标

标题的图标(对于正在绘制的部分)。

图标对齐

标题中图标的对齐方式(Qt::Alignment)。

方向

一个决定标题是视图上方的水平标题还是左侧的垂直标题的 Qt::Orientation 值。

position

一个 SectionPosition 值,给出标题部分相对于其他部分的位置。

部分

包含正在绘制部分的内容。

selectedPosition

一个 SelectedPosition 值,给出选定部分相对于被绘制的部分的位置。

排序指示

一个描述部分排序指示绘制方向的 SortIndicator 值。

文本

当前绘制的部分的文本。

textAlignment

标题部分内文本的 Qt::Alignment 对齐方式。

树分支指示#

在树视图中,分支指示是通过使用 PE_IndicatorBranch 的样式来绘制的。在这里,我们认为指示符是描述树中节点关系的指示符。通用的 QStyleOption 被发送到样式以绘制这些元素。各种分支类型由状态描述。由于没有特定的样式选项,我们仅展示状态表

状态

设置条件

State_Sibling

树中的节点有一个兄弟节点(即同一列中还有另一个节点)。

State_Item

这个分支指示符有一个项目。

State_Children

分支有孩子(即可以在分支处打开新的子树)。

State_Open

分支指示符有一个打开的子树。

树形视图(和树小部件)使用样式来绘制树的分支(节点)。

QStyleOption 作为样式用于 PE_IndicatorBranch,根据分支的类型设置状态标志。

由于分支指示器没有树形结构,我们只展示了一幅Java风格的树形图片。每个状态用特定颜色的矩形标记在图片中(即,这些矩形不是边界矩形)。图中包含了你需要知道的所有的状态组合。

../_images/branchindicatorimage.png

工具箱#

PM_SmallIconSize 用于尺寸提示。

QToolBox 是一个容器,其中包含一组小部件。它为每个小部件有一个标签,一次显示一个。工具箱将其显示的组件(工具箱按钮和所选小部件)排列在一个 QVBoxLayout 中。工具箱的样式树如下所示

../_images/toolbox.png

我们展示了Plastique风格的工具箱图片。

../_images/toolboximage.png

在Plastique风格以及其他内置Qt样式中,所有元素都具有相同的边界矩形。

工具箱的样式选项为 QStyleOptionToolBox 。它包含工具箱内容的文本和图标。由 QToolBox 设置的唯一状态是 State_Sunken,当用户用鼠标按下标签向下时设置。其他 QStyleOptionToolBox 成员包括

成员

内容

图标

工具箱标签上的图标。

文本

工具箱标签上的文本。

尺寸 grip#

尺寸 grip使用 CT_SizeGrip 计算其尺寸提示。像素度量 PM_SizeGripSize 目前在Qt中没有使用。QSizeGrip 图片在Plastique风格中的元素树如下

../_images/sizegrip.png ../_images/sizegripimage.png

我们在 QMainWindow 的右下角展示了尺寸 grip。

尺寸 grip样式选项,QStyleOptionSizeGrip ,除了来自 QStyleOption 的公共成员外,还有一个成员

成员

内容

角落

一个描述握柄位于窗口(或等效)哪个角落的 Qt::Corner 值。

橡皮筋#

QRubberBand(橡皮带)的样式树由两个节点组成。

../_images/rubberband.png

我们展示了一个具有橡皮带的Java样式窗口在(QMdiArea(多文档界面区))中被移动的图像

../_images/rubberbandimage.png

橡皮带的样式选项为QStyleOptionRubberBand(橡皮带样式选项) 。其成员包括:

成员

内容

opaque

布尔值,当橡皮带必须以不透明样式(即颜色)绘制时为真。

形状

一个Shape(形状)枚举值,用于存储橡皮带的形状(可以是矩形或线条)。

浮动小部件

当浮动小部件布局其内容时,它会向样式请求以下像素指标:PM_DockWidgetSeparatorExtent(浮动小部件分隔符大小)、PM_DockWidgetTitleBarButtonMargin(浮动小部件标题按钮边距)、PM_DockWidgetFrameWidth(浮动小部件框架宽度)和PM_DockWidgetTitleMargin(浮动小部件标题边距)。它还使用SE_DockWidgetCloseButton(浮动小部件关闭按钮)和SE_DockWidgetFloatButton(浮动小部件浮动按钮)计算浮动按钮和关闭按钮的边界矩形。

../_images/dockwidget.png

虚线表示发送者保持箭头接收者的实例(即,不是用于绘制的样式元素)。当一个浮动小部件从其主窗口分离时(即,它是一个顶级窗口),它只绘制PE_frameDockWidget。如果它已停靠,它绘制指示器浮动小部件大小调整把手。我们以plastique样式展示了停靠和浮动状态下的浮动小部件。

../_images/dockwidgetimage.png

样式选项为QStyleOptionDockWidget(浮动小部件样式选项)

成员

内容

可关闭

布尔值,表示浮动小部件是否可关闭。

可浮动

布尔值,表示浮动小部件是否可浮动(即,可以从其所在的主窗口中分离)。

可移动

布尔值,表示窗口是否可移动(即,可以移动到其他浮动小部件区域)。

标题

浮动小部件的标题文本。

对于按钮,使用QStyleOptionButton(按钮样式选项)(参见工具按钮以获取内容描述)。浮动小部件的大小调整把手具有纯粹的QStyleOption(样式选项)。