警告
本节包含从C++自动翻译到Python的代码片段,可能包含错误。
样式和样式感知小部件¶
样式和小部件的样式化。
样式(继承自QStyle的类)代表小部件进行绘制,并封装了GUI的外观和感觉。QStyle类是一个抽象基类,封装了GUI的外观和感觉。Qt的内置小部件使用它来执行几乎所有的绘制工作,确保它们看起来与等效的原生小部件完全一样。
Qt 提供了一系列内置样式。某些样式仅在特定平台上可用。自定义样式可以通过插件或通过使用 create() 创建特定样式类的实例并使用 setStyle() 进行设置来提供。
自定义样式¶
为了自定义现有样式,继承 QProxyStyle 并重新实现所需的虚方法。QProxyStyle 允许指定某个基础样式,或者如果未指定基础样式,它将自动使用应用程序样式。前者提供了对基础样式的完全控制,如果自定义期望某种样式行为,则效果最佳,而后者提供了一种平台无关的方式来自定义应用程序样式,默认使用本机平台样式。
实现自定义样式¶
QCommonStyle 为完整的自定义样式实现提供了一个方便的基类。方法与 QProxyStyle 相同,但继承 QCommonStyle 并重新实现适当的虚方法。实现一个完整的自定义样式有些复杂,因此我们提供了这个概述。我们将逐步介绍如何为单个 Qt 小部件设置样式。我们将检查 QStyle 的虚函数、成员变量和枚举。
本文档中不涉及单个小部件样式的部分应按顺序阅读,因为后面的部分往往依赖于前面的部分。小部件的描述可以在实现样式时用作参考。然而,在某些情况下,您可能需要查阅Qt源代码。阅读本文档后,样式化过程的顺序应该会变得清晰,这将帮助您定位相关代码。
要开发样式感知的小部件(即符合其绘制样式的小部件),您需要使用当前样式来绘制它们。本文档展示了小部件如何绘制自己以及样式为它们提供了哪些可能性。
小部件样式类¶
这些类用于自定义应用程序的外观和样式。
QGraphicsAnchorLayout 类提供了一个布局,可以在图形视图中将小部件锚定在一起。
QGraphicsAnchor 类表示在 QGraphicsAnchorLayout 中两个项目之间的锚点。
QCommonStyle 类封装了 GUI 的通用外观和感觉。
QPixmapStyle 类提供了编写基于像素图的样式的机制。
QStyle类是一个抽象基类,封装了GUI的外观和感觉。
QStyleFactory 类用于创建 QStyle 对象。
QStyleOption 类存储了 QStyle 函数使用的参数。
QStyleHintReturn 类提供了返回不仅仅是基本数据类型的样式提示。
QStyleHintReturnMask 类提供了返回 QRegion 的样式提示。
QStyleHintReturnVariant 类提供了返回 QVariant 的样式提示。
QStylePainter 类是一个方便类,用于在小部件内绘制 QStyle 元素。
QWindowsStyle 类提供了类似 Microsoft Windows 的外观和感觉。
QStyle 实现¶
QStyle 的 API 包含绘制小部件的函数、执行常见和困难任务的静态辅助函数(例如,计算滑块手柄的位置)以及在绘制过程中执行各种必要计算的函数(例如,小部件计算其大小提示)。该样式还帮助一些小部件进行内容的布局。此外,它创建了一个包含用于绘制的 QBrushes 的 QPalette。
QStyle 绘制图形元素;一个元素是一个小部件或小部件的一部分,如按钮斜面、窗口框架或滚动条。大多数绘制函数现在接受四个参数:
一个枚举值,指定要绘制的图形元素
一个
QStyleOption指定如何以及在何处渲染该元素一个应该用于绘制元素的 QPainter
一个
QWidget,用于在其上进行绘图(可选)
当一个小部件请求样式绘制一个元素时,它会向样式提供一个QStyleOption,这是一个包含绘制所需信息的类。由于QStyleOption,可以在不链接任何小部件代码的情况下让QStyle绘制小部件。这使得可以在任何绘图设备上使用QStyle的绘制函数,也就是说,你可以在任何小部件上绘制组合框,而不仅仅是在QComboBox上。
小部件作为最后一个参数传递,以防样式需要它来执行特殊效果(例如macOS上的动画默认按钮),但这不是强制性的。
在本节中,我们将查看样式元素、样式选项以及QStyle的功能。最后,我们将描述如何使用调色板。
在Qt中,项目视图中的项目由delegates绘制。项目视图的标题仍然由样式绘制。Qt的默认委托QStyledItemDelegate通过当前样式部分绘制其项目;它绘制复选框指示器并计算项目组成元素的边界矩形。在本文档中,我们仅描述如何实现QStyle子类。如果您希望添加对QStyledItemDelegate不支持的其他数据类型的支持,您需要实现一个自定义委托。请注意,必须为每个单独的小部件以编程方式设置委托(即,默认委托不能作为插件提供)。
样式元素¶
样式元素是图形用户界面(GUI)的图形部分。一个小部件由样式元素的层次结构(或树)组成。例如,当样式收到绘制按钮的请求时(例如来自QPushButton),它会绘制一个标签(文本和图标)、一个按钮斜面和一个焦点框。按钮斜面又由斜面周围的框架和另外两个元素组成,我们稍后会看到。下面是按钮元素树的概念图。当我们浏览各个小部件时,我们将看到QPushButton的实际树。
小部件不一定通过要求样式只绘制一个元素来绘制。小部件可以多次调用样式来绘制不同的元素。一个例子是QTabWidget,它分别绘制其标签和框架。
有三种元素类型:基本元素、控制元素和复杂控制元素。这些元素由ComplexControl、ControlElement和PrimitiveElement枚举定义。每个元素枚举的值都有一个前缀来标识它们的类型:CC_表示复杂元素,CE_表示控制元素,PE_表示基本元素。我们将在接下来的三个部分中了解这些不同元素的定义,并查看使用它们的小部件示例。
QStyle 类的描述包含了这些元素及其在小部件样式中的角色列表。我们将在为单个小部件设置样式时看到它们的使用方法。
原始元素¶
原始元素是GUI元素,这些元素常见且经常被多个小部件使用。例如框架、按钮斜面以及用于旋转框、滚动条和组合框的箭头。原始元素不能独立存在:它们总是更大结构的一部分。它们不参与与用户的交互,而是GUI中的被动装饰。
控制元素¶
控制元素执行操作或向用户显示信息。控制元素的示例包括按钮、复选框以及表格和树视图中的标题部分。控制元素不一定是完整的部件,如按钮,也可以是部件的一部分,如标签栏标签和滚动条滑块。它们与原始元素的不同之处在于它们不是被动的,而是在与用户的交互中发挥作用。由多个元素组成的控件通常使用样式来计算元素的边界矩形。可用的子元素由SubElement枚举定义。此枚举仅用于计算边界矩形;子元素不是像原始元素、控制元素和复杂元素那样要绘制的图形元素。
复杂控制元素¶
复杂控制元素包含子控件。复杂控件的行为会根据用户使用鼠标处理它们的位置以及按下的键盘键而有所不同。这取决于鼠标悬停或按下的子控件(如果有)。复杂控件的例子包括滚动条和组合框。使用滚动条时,您可以使用鼠标移动滑块并按下向上和向下按钮。可用的子控件由SubControl枚举定义。
除了绘图之外,样式还需要向小部件提供有关鼠标按下时所在的子控件(如果有的话)的信息。例如,QScrollBar需要知道用户是按下了滑块、滑块槽还是其中一个按钮。
请注意,子控件与前一节中描述的控件元素不同。您不能使用样式来绘制子控件;样式只会计算应绘制子控件的边界矩形。然而,复杂元素通常使用控件和基本元素来绘制其子控件,这是Qt内置样式和Java样式经常使用的方法。例如,Java样式使用PE_IndicatorCheckBox来绘制组框中的复选框(这是CC_GroupBox的子控件)。一些子控件具有等效的控件元素,例如滚动条滑块(SC_SCrollBarSlider和CE_ScrollBarSlider)。
其他QStyle任务¶
如前所述,样式元素和小部件使用样式来计算子元素和子控件的边界矩形。像素度量,即依赖于样式的屏幕像素大小,也在绘制时用于测量。可用的矩形和像素度量由QStyle中的三个枚举表示:SubElement、SubControl和PixelMetric。枚举的值很容易识别,因为它们以SE_、SC_和PM_开头。
样式还包含一组样式提示,这些提示表示为StyleHint枚举中的值。所有小部件在不同样式中并不具有相同的功能和外观。例如,当菜单中的菜单项无法在屏幕上的一列中全部显示时,某些样式支持滚动,而其他样式则绘制多列以适应所有项。
样式通常有一组标准图像(例如警告、问题和错误图像)用于消息框、文件对话框等。QStyle 提供了 StandardPixmap 枚举。其值代表标准图像。Qt 的小部件使用这些图像,因此当您实现自定义样式时,应提供该样式所使用的图像。
该样式计算布局中小部件之间的间距。样式可以通过两种方式处理这些计算。您可以设置PM_LayoutHorizontalSpacing和PM_LayoutVerticalSpacing,这是Java样式的方式(通过QCommonStyle)。或者,如果您需要对此部分的布局进行更多控制,可以实现layoutSpacing()和QStyle::layoutSpacingImplementation()。在这些函数中,您可以根据控件类型(ControlType)为不同的尺寸策略(Policy)以及相关小部件的样式选项来计算间距。
样式选项¶
QStyleOption 的子类包含了样式化各个元素所需的所有信息。样式选项通常是在栈上实例化的,并由 QStyle 函数的调用者填充。根据绘制的元素,样式会期望不同的样式选项类。例如,QStyle::PE_FrameFocusRect 元素期望一个 QStyleOptionFocusRect 参数,并且可以创建自定义子类供自定义样式使用。出于性能原因,样式选项保留了公共变量。
小部件可以处于多种不同的状态,这些状态由State枚举定义。一些状态标志根据小部件的不同有不同的含义,但其他一些状态对所有小部件都是通用的,比如State_Disabled。是QStyleOption通过initFrom()设置通用状态;其余的状态由各个小部件自行设置。
最值得注意的是,样式选项包含要绘制的小部件的调色板和边界矩形。大多数小部件都有专门的样式选项。例如,QPushButton 和 QCheckBox 使用 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_Active和State_Enabled状态标志来找到这些状态。每组包含由QPalette::ColorRole枚举给出的某些颜色角色。这些角色描述了在哪些情况下应该使用这些颜色(例如,用于绘制小部件背景、文本或按钮)。
颜色的使用方式取决于样式。例如,如果样式使用渐变,可以使用调色板中的颜色,并通过QColor::darker()和QColor::lighter()使其变暗或变亮来创建渐变。一般来说,如果你需要一个调色板中没有提供的画笔,你应该尝试从其中一个派生出来。
QPalette,提供调色板,存储不同小部件状态和颜色角色的颜色。样式的调色板由standardPalette()返回。当在应用程序(setStyle())或小部件(setStyle())上设置新样式时,标准调色板不会自动安装,因此您必须自己使用(setPalette())或(setPalette())设置调色板。
不建议硬编码颜色,因为应用程序和单个小部件可以设置自己的调色板,并使用其样式的调色板进行绘制。请注意,Qt的小部件都没有设置自己的调色板。Java风格确实硬编码了一些颜色,但这只是作者的决定;不建议这样做。当然,样式不应该期望与任何调色板都能很好地搭配。
实现问题¶
在实现样式时,有几个问题需要考虑。我们将在这里提供一些实现上的提示和建议。
在实现样式时,有必要查看小部件的代码以及基类及其祖先的代码。这是因为小部件以不同的方式使用样式,因为不同样式的虚函数中的实现可能会影响绘图的状态(例如,通过改变QPainter状态而不恢复它,并在不使用适当的像素度量和子元素的情况下绘制一些元素)。
建议样式不要使用sizeFromContents()函数改变小部件的建议大小,而是让QCommonStyle的实现来处理。如果需要更改,应尽量保持更改较小;如果小部件的布局在各种样式中看起来差异很大,应用程序开发可能会变得困难。
Java 风格¶
我们已经实现了一种类似于Java默认外观和感觉(以前称为Metal)的样式。我们这样做是因为它相对容易实现,并且我们希望为这篇概述文档构建一个样式。为了保持简单且不过于广泛,我们对样式进行了一些简化,但Qt完全能够制作出该样式的精确副本。然而,目前没有具体的计划将该样式作为Qt的一部分来实现。
在本节中,我们将探讨一些实现问题。最后,我们将看到一个关于Java小部件样式的完整示例。我们将在文档中继续使用Java样式作为示例和小部件图像。实现本身有些复杂,并不建议您通读它。
设计与实现¶
设计样式的第一步是选择基类。我们选择子类化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()
首先,我们让QStyleOption使用initFrom()为所有小部件设置通用的信息。我们稍后会详细讨论这一点。
QStyleOption 的 down 变量在用户按下框时为 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 标志被设置。只有在小部件设置了 WA_HoverEnabled 窗口标志时,State_MouseOver 才会被设置。请注意,必须在 Qt 中启用键盘导航才能包含 State_HasEditFocus;默认情况下不包含它。
除了设置状态标志外,QStyleOption 还包含有关小部件的其他信息:direction 是布局的方向,rect 是小部件的边界矩形(绘制的区域),palette 是用于绘制小部件的 QPalette,fontMetrics 是小部件使用的字体的度量。
我们提供了一个复选框的图像和与之匹配的样式选项。
上述复选框将在其样式选项中具有以下状态标志:
状态标志
设置
State_Sunken是
State_NoChange否
State_On是
State_Off否
State_MouseOver是
State_Enabled是
State_HasFocus是
State_KeyboardFocusChange否
State_Active是
QCheckBox 在 paintEvent() 中使用样式选项 opt 和 QStylePainter p 绘制自身。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()中CE_CheckBoxIndicator的Java实现:
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())
State_Focus如果小部件具有焦点,则设置(参见
hasFocus())
State_KeyboardFocusChange当用户使用键盘更改焦点时设置(参见 Qt::WA_KeyboardFocusChange)
State_MouseOver如果鼠标光标在小部件上,则设置
State_Active如果小部件是活动窗口的子窗口,则设置。
State_HasEditFocus如果小部件具有编辑焦点,则设置
小部件的其他常见成员有:
用于复杂样式元素的复杂样式选项(继承自QStyleOptionComplex的类)共享两个变量:subControls和activeSubControls。这两个变量都是SubControl枚举值的OR组合。它们指示复杂控件由哪些子控件组成以及这些控件中哪些当前处于活动状态。
如前所述,样式计算小部件内容的大小,小部件根据此计算其大小提示。此外,复杂控件还使用样式来测试鼠标位于哪个子控件上。
小部件参考¶
事不宜迟,我们展示小部件的演练;每个小部件都有其自己的子部分。
标签¶
在Qt中,QTabBar使用样式来绘制其标签。标签可以存在于QTabWidget中,它包含一个QTabBar,或者作为一个单独的栏存在。如果该栏不是标签小部件的一部分,它会绘制自己的基础。
QTabBar 负责布局标签页,因此样式无法控制标签页的位置。然而,在布局其标签页时,标签栏会向样式请求 PM_TabBarTabHSpace 和 PM_TabBarTabVSpace,这是标签栏标签(图标和文本)最小尺寸之外的额外宽度和高度。样式还可以在布局之前进一步影响标签的大小,因为标签栏会请求 CT_TabBarTab。当标签栏作为小部件的一部分时,其边界矩形由标签小部件决定(仍然考虑 CT_TabBarTab)。
标签栏负责绘制当所有标签无法完全显示时出现在标签栏上的按钮。它们的位置不由样式控制,但这些按钮是QToolButton,因此由样式绘制。
以下是QTabWidget和QTabBar的样式结构:
虚线表示QTabWidget包含一个标签栏,但不绘制标签栏本身。QTabBar在不作为标签小部件的一部分时仅绘制其基线,并且当所有标签不适合时,它会保留两个滚动条的工具按钮;有关它们的元素树,请参见Tool Buttons。还要注意,由于按钮是标签栏的子项,它们在栏之后绘制。标签的边界矩形与基线重叠PM_TabBarBaseOverlap。
这是一个Java风格的标签小部件:
在Java风格中,标签栏的形状和标签与CE_TabBarTab具有相同的边界矩形。请注意,标签与标签小部件框架重叠。标签栏的底部(如果绘制)是标签和框架重叠的区域。
标签页的样式选项(QStyleOptionTab)包含了绘制标签页所需的信息。该选项包含标签在标签栏中的位置、选中标签的位置、标签的形状、文本、图标以及图标的大小。
由于Java风格的标签页不重叠,我们还展示了一个常见风格的标签小部件的图像。请注意,如果您希望标签页水平重叠,您可以在CE_TabBarTabShape中绘制标签页时实现;标签页的边界矩形不会被标签栏改变。标签页在北方标签栏形状中从左到右绘制,在东方标签栏形状中从上到下绘制,依此类推。选中的标签页最后绘制,以便于在其他标签页上绘制(如果它要更大)。
以下是标签栏可以为其标签设置的状态表:
状态
状态设置时间
State_Sunken选项卡被鼠标按下。
State_Selected如果是当前标签页。
State_HasFocus标签栏具有焦点并且标签被选中。
请注意,即使标签栏未被禁用,单个标签也可能被禁用。如果标签栏处于活动状态,标签也将处于活动状态。
以下是QStyleOptionTab的成员表:
成员
内容
cornerWidgets
CornerWidget枚举的标志,指示标签栏是否具有以及具有哪些角部件。
icon
标签的QIcon。
iconSize
图标的大小。
position
一个TabPosition枚举值,表示标签在栏上相对于其他标签的位置。
行
保存标签所在的行。
selectedPosition
SelectedPosition 枚举的一个值,指示所选选项卡是否与选项卡相邻或是选项卡本身。
形状
一个
Shape枚举的值,指示选项卡是否具有圆角或三角形角以及选项卡的方向。text
标签文本。
标签小部件的框架使用QStyleOptionTabWidgetFrame作为样式选项。我们在这里列出其成员。除了常见的标志外,它没有设置状态。
成员
内容
leftCornerWidgetSize
左侧角落小部件的QSize(如果有的话)。
rightCornerWidgetSize
右侧角落小部件的QSize(如果有的话)。
lineWidth
保存用于绘制面板的线条宽度。
midLineWith
该值目前始终为0。
shape
标签栏上标签的形状。
tabBarSize
标签栏的QSize。
滚动条¶
以下是滚动条的样式结构:
QScrollBar 简单地创建其样式选项,然后绘制 CC_ScrollBar。一些样式使用 PE_PanelButtonBevel 绘制添加页面和子页面的背景,并且还使用指示箭头来绘制下一行和上一行指示器中的箭头;我们没有将这些包含在树中,因为它们的使用取决于各个样式。样式的 PM_MaximumDragDistance 是鼠标可以从滚动条的边界移动的最大距离(以像素为单位),并且仍然可以移动手柄。
这是一个Java风格的滚动条图片:
你可能会注意到滚动条与Java的略有不同,因为它有两个向上指示器。我们这样做是为了展示你可以为一个子控件设置两个独立的边界矩形。滚动条是一个完全由Java样式实现的小部件的例子 - QCommonStyle 不参与绘制。
我们来看一下滚动条在样式选项上可以设置的不同状态:
状态
状态设置时间
State_Horizontal滚动条是水平的。
QScrollBar 的样式选项是 QStyleOptionSlider。其成员列在下表中。该选项由所有 QAbstractSlider 使用;我们在这里只描述与滚动条相关的成员。
成员
内容
maximum
滚动条的最大值。
minimum
滚动条的最小值。
notchTarget
凹槽之间的像素数。
orientation
Qt::Orientation 枚举的一个值,用于指定滚动条是垂直还是水平。
pageStep
在页面步骤中增加或减少滑块值的数量(相对于滑块的大小及其值范围)。
singleStep
单步(或行)步骤中滑块值增加或减少的数量。
sliderValue
滑块的值。
sliderPosition
滑块手柄的位置。如果滚动条是
tracking,则与sliderValue相同。如果不是,滚动条在鼠标释放手柄之前不会更新其值。upsideDown
保存滚动条增加其值的方向。这用于代替所有抽象滑块的QStyleOption::direction。
滑块¶
在计算滑块的尺寸提示时,PM_SliderThickness 和 PM_SliderLength 是从样式中查询的。与滚动条一样,QSlider 只允许用户在鼠标位于滑块边界 PM_MaximumDragDistance 范围内时移动手柄。当它绘制自身时,它会创建样式选项并使用 CC_Slider 调用 drawComplexControl():
我们还展示了一张Java风格的滑块图片。我们展示了子元素的边界矩形,因为所有的绘图都是在CC_Slider中完成的。
QSlider 使用 QStyleOptionSlider,就像所有 QAbstractSlider 一样。我们提供了一个表格,列出了影响 QSlider 的成员:
成员
内容
maximum
滑块的最大值。
minimum
滑块的最小值。
notchTarget
这是每个刻痕之间的像素数。
orientation
一个 Qt::Orientation 枚举值,指示滑块是垂直还是水平。
pageStep
在页面步骤上增加或减少滑块值的数量。
singleStep
单步(或行)步骤中滑块值增加或减少的数量。
sliderValue
滑块的值。
sliderPosition
滑块的位置以滑块值给出。如果滑块正在
tracking,这将等于sliderValue;如果不是,滑块的值将不会改变,直到鼠标释放手柄。upsideDown
此成员用于代替QStyleOption::direction用于所有抽象滑块。
你应该注意到滑块不使用方向进行反向布局;它使用upsideDown。
旋转框¶
当QSpinBox绘制自身时,它会创建一个QStyleOptionSpinBox并请求样式绘制CC_SpinBox。编辑字段是一个作为微调框子部件的行编辑。字段的尺寸由样式通过SC_SpinBoxEditField计算。
以下是旋转框的样式树。样式不需要使用按钮面板原语来绘制指示器背景。您可以在树下方看到一个图像,显示Java样式中QSpinBox的子元素。
QStyleOptionSpinBox,这是用于微调框的样式选项。它可以在微调框上设置以下状态:
状态
状态设置时间
State_Sunken如果鼠标按下子控件
CC_SpinUp或CC_SpinDown中的一个,则设置此状态。
旋转框样式选项中的其余成员是:
属性
功能
frame
布尔值,如果旋转框要绘制框架,则为
true。buttonSymbols
ButtonSymbols 枚举的值,决定上下按钮上的符号。
stepEnabled
StepEnabled 枚举的一个值,指示哪个微调框按钮被按下。
标题栏¶
标题栏复合控件,CC_TitleBar,用于绘制QMdiArea中内部窗口的标题栏。它通常由窗口标题、关闭、最小化、系统菜单和最大化按钮组成。某些样式还提供用于阴影窗口的按钮,以及用于上下文相关帮助的按钮。
条形图在CC_TitleBar中绘制,不使用任何子元素。各个样式如何绘制它们的按钮由它们自己决定,但样式应提供按钮的标准像素图。
在Java风格的标题栏上的图像中,我们展示了Java风格支持的子元素的边界矩形(所有这些子元素都是用标准像素图绘制的)。通常使用PE_PanelButtonTool来绘制按钮背景,但这并不是强制性的。
标题栏的样式选项是 QStyleOptionTitleBar。其成员包括:
成员
内容
icon
标题栏的图标。
text
标题栏标签的文本。
windowFlags
Qt::WindowFlag 枚举的标志。
QMdiArea用于窗口管理的窗口标志。titleBarState
这是包含标题栏的窗口的
windowState()。
组合框¶
一个QComboBox使用样式来绘制不可编辑框的按钮和标签,使用CC_ComboBox和CE_ComboBoxLabel。
当用户点击组合框时弹出的列表是由一个delegate绘制的,我们在本概述中不涉及这部分内容。然而,您可以使用样式通过子元素SC_ComboBoxListBoxPopup来控制列表的大小和位置。样式还决定了可编辑框的编辑字段应该位于何处,使用SC_ComboBoxEditField;该字段本身是一个QLineEdit,它是组合框的子元素。
我们在一个Java风格的下拉框上显示了一张图片,其中我们勾勒了它的子元素和子元素矩形:
Java组合框不使用焦点矩形;当它获得焦点时,它会改变其背景颜色。SC_ComboBoxEdit字段被QComboBox用于计算编辑字段的大小以及用于计算组合框标签大小的样式。
组合框的样式选项是 QStyleOptionComboBox。它可以设置以下状态:
状态
设置时间
State_Selected该框不可编辑且具有焦点。
State_Sunken
SC_ComboBoxArrow是激活的。
State_on盒子的容器(列表)是可见的。
其他成员的样式选项有:
成员
内容
currentIcon
组合框当前(选中)项的图标。
currentText
框中当前项目的文本。
editable
控制组合框是否可编辑。
frame
确定组合框是否有边框。
iconSize
当前项目图标的大小。
popupRect
组合框弹出列表的边界矩形。
分组框¶
在计算大小提示时,QGroupBox 从样式中获取三个像素度量:PM_IndicatorWidth、PM_CheckBoxLabelSpacing 和 PM_IndicatorHeight。QGroupBox 具有以下样式元素树:
Qt 对复选框的绘制方式没有限制;Java 风格使用 CE_IndicatorCheckBox 来绘制它。有关完整的树结构,请参见 Check and Radio Buttons。
我们还提供了一个带有子控件和子控件矩形的小部件图像:
分组框的样式选项是 QStyleOptionGroupBox。可以在其上设置以下状态:
状态
设置时间
State_On复选框已选中。
State_Sunken复选框被按下。
State_Off复选框未选中(或没有复选框)。
QStyleOptionGroupBox 的剩余成员是:
成员
内容
features
描述组框框架的
FrameFeatures枚举的标志。lineWidth
绘制面板时使用的线条宽度。这始终为1。
text
组框的文本。
textAlignment
组框标题的对齐方式。
textColor
文本的QColor。
分割器¶
由于分隔器的结构简单且不包含任何子元素,我们不包含任何分隔器的图像。CE_Splitter不使用任何其他元素或指标。
对于其样式选项,分割器使用基类 QStyleOption。它可以在其上设置以下状态标志:
状态
设置时间
State_Horizontal如果是水平分割器则设置。
QSplitter 不使用 initFrom() 来设置其选项;它自己设置 State_MouseOver 和 State_Disabled 标志。
进度条¶
CE_ProgressBar 元素由 QProgressBar 使用,并且它是该小部件唯一使用的元素。我们从样式结构开始:
这里是一个常见样式的进度条(Java样式的边界矩形是相等的):
QProgressBar 的样式选项是 QStyleOptionProgressBar。进度条不设置任何状态标志,但选项的其他成员是:
成员
内容
minimum
条形图的最小值。
maximum
柱状图的最大值。
progress
进度条的当前值。
textAlignment
文本在标签中的对齐方式。
textVisible
标签是否被绘制。
text
标签文本。
orientation
进度条可以是垂直或水平的。
invertedAppearance
进度条是倒置的(即水平条从右到左)。
bottomToTop
布尔值,如果为
true,则将垂直进度条的标签旋转90度。
工具栏¶
工具栏是main window framework的一部分,并与它们所属的QMainWindow合作,同时构建其样式选项。主窗口有4个可以放置工具栏的区域。它们位于窗口的四个侧面(即北、南、东和西)。在每个区域内,可以有多个工具栏行;一行由具有相同方向(垂直或水平)的工具栏并排组成。
Toolbars 在 Qt 中由三个元素组成:CE_ToolBar、PE_IndicatorToolBarHandle 和 PE_IndicatorToolBarSeparator。是 QMainWindowLayout 计算边界矩形(即工具栏及其内容的位置和大小)。主窗口在计算工具栏的大小时,也会使用工具栏中项目的 sizeHint()。
以下是 QToolBar 的元素树:
虚线表示QToolBar保持了一个QToolBarLayout的实例,并且QToolBarSeparators由QToolBarLayout保持。当工具栏浮动时(即拥有自己的窗口),绘制PE_FrameMenu元素,否则QToolBar绘制CE_ToolBar。
这是一个Java风格的工具栏图片:
QToolBarSaparator 使用 QStyleOption 作为其样式选项。如果它所在的工具栏是水平的,它会设置 State_Horizontal 标志。除此之外,它们使用 initFrom()。
QToolBar 的样式选项是 QStyleOptionToolBar。唯一设置的状态标志(除了常见标志外)是 State_Horizontal,如果工具栏是水平的(即在北部或南部工具栏区域)。样式选项的成员变量是:
成员
内容
features
保存工具栏是否可移动,值为ToolBarFeature,可以是Movable或None。
lineWidth
工具栏框架的宽度。
midLineWidth
此变量当前未使用,始终为0。
positionOfLine
工具栏线在其所属工具栏区域中的位置。
positionWithinLine
工具栏在工具栏行中的位置。
toolBarArea
工具栏所在的工具栏区域。
项目查看标题¶
这是绘制Qt项目视图标题的样式。项目视图保持各个部分的尺寸。还要注意,委托可能使用样式来绘制项目周围的装饰和框架。例如,QItemDelegate 绘制 PE_FrameFocusRect 和 PE_IndicatorItemViewItemCheck。
这里有一个QTableWidget显示Java标题的边界矩形:
QHeaderView 使用 CT_HeaderSection、PM_HeaderMargin 和 PM_HeaderGripMargin 进行大小和点击测试计算。PM_HeaderMarkSize 目前未被 Qt 使用。QTableView 将左上角的按钮(即垂直和水平标题相交的区域)绘制为 CE_Header。
标题视图的样式选项是 QStyleOptionHeader。视图一次绘制一个标题部分,因此数据是针对正在绘制的部分。其内容为:
成员
内容
icon
标题的图标(用于正在绘制的部分)。
iconAlignment
标题中图标(Qt::Alignment)的对齐方式。
orientation
一个 Qt::Orientation 值,决定标题是视图上方的水平标题还是左侧的垂直标题。
位置
一个
SectionPosition值,表示标题部分相对于其他部分的位置。section
保存正在绘制的部分。
selectedPosition
一个
SelectedPosition值,给出所选部分相对于正在绘制的部分的位置。sortIndicator
一个
SortIndicator值,用于描述应绘制部分排序指示器的方向。text
当前绘制部分的文本。
textAlignment
标题部分内文本的Qt::Alignment。
树枝指标¶
树视图中的分支指示器由样式PE_IndicatorBranch绘制。我们在这里将指示器视为描述树中节点关系的指示器。通用的QStyleOption被发送到样式以绘制这些元素。各种分支类型由状态描述。由于没有特定的样式选项,我们简单地呈现状态表:
状态
设置时间
State_Sibling树中的节点有一个兄弟节点(即在同一列中有另一个节点)。
State_Item此分支指示器有一个项目。
State_Children该分支有子节点(即可以在该分支处打开一个新的子树)。
State_Open分支指示器有一个打开的子树。
树视图(和树小部件)使用样式来绘制树的分支(节点)。
QStyleOption 用作 PE_IndicatorBranch 的样式,其状态标志根据分支类型设置。
由于分支指标没有树结构,我们仅展示了一个Java风格的树图像。每个状态在图像中用特定颜色的矩形标记(即这些矩形不是边界矩形)。图像中展示了您必须了解的所有状态组合。
工具箱¶
PM_SmallIconSize 用于 sizeHints。
QToolBox 是一个容器,用于存放一组小部件。它为每个小部件都有一个标签,并且一次只显示其中一个。工具箱将其显示的组件(工具箱按钮和选中的小部件)布局在 QVBoxLayout 中。工具箱的样式树如下所示:
我们展示了一个Plastique风格的工具箱图像:
所有元素在Plastique风格以及其他内置的Qt风格中都具有相同的边界矩形。
工具箱的样式选项是QStyleOptionToolBox。它包含工具箱内容的文本和图标。QToolBox设置的唯一状态是State_Sunken,当用户用鼠标按下标签时设置。其余的QStyleOptionToolBox成员是:
成员
内容
icon
工具箱选项卡上的图标。
text
工具箱标签上的文本。
大小调整手柄¶
大小手柄使用CT_SizeGrip计算其大小提示。像素度量PM_SizeGripSize目前未被Qt使用。在Plastique风格中,QSizeGrip的图像元素树如下:
我们在QMainWindow的右下角显示大小调整手柄。
大小手柄样式选项,QStyleOptionSizeGrip,除了来自QStyleOption的常见成员外,还有一个成员:
成员
内容
corner
一个Qt::Corner值,描述了窗口(或等效物)中抓握位置所在的角落。
橡皮筋¶
QRubberBand 的样式树由两个节点组成。
我们展示了一个Java风格窗口在QMdiArea中使用橡皮筋移动的图像:
橡皮筋的样式选项是 QStyleOptionRubberBand。其成员包括:
成员
内容
opaque
布尔值,如果必须使用不透明样式(即颜色)绘制橡皮筋,则为
true。形状
一个
Shape枚举值,用于保存带的形状(可以是矩形或线)。
停靠小部件¶
当停靠小部件布局其内容时,它会向样式询问这些像素度量:PM_DockWidgetSeparatorExtent、PM_DockWidgetTitleBarButtonMargin、PM_DockWidgetFrameWidth 和 PM_DockWidgetTitleMargin。它还使用 SE_DockWidgetCloseButton 和 SE_DockWidgetFloatButton 计算浮动和关闭按钮的边界矩形。
虚线表示发送者保留箭头接收者的实例(即,它不是用于绘制的样式元素)。当停靠小部件从其主窗口分离时(即,它是一个顶级窗口),它只绘制PE_frameDockWidget。如果它被停靠,它会绘制指示器停靠小部件调整大小的手柄。我们在plastique样式中展示了停靠和浮动状态的停靠小部件:
样式选项是 QStyleOptionDockWidget :
成员
内容
closeable
布尔值,表示停靠窗口是否可以关闭。
floatable
布尔值,表示停靠窗口是否可以浮动(即从其所在的主窗口中分离)。
movable
布尔值,表示窗口是否可移动(即可以移动到其他停靠部件区域)。
title
停靠窗口的标题文本。
对于按钮,使用QStyleOptionButton(有关内容描述,请参见工具按钮)。停靠小部件的调整大小手柄使用了一个简单的QStyleOption。