QT学习(20):QStyle和自定义样式

QStyle
样式(继承自QStyle类)代表控件的绘制并封装GUI的外观。QStyle是一个封装了GUI外观的抽象基类。Qt使用QStyle去执行几乎所有的内置控件的绘制,确保控件外观和原生控件风格风格相同。

class Q_WIDGETS_EXPORT QStyle : public QObject{};

QProxyStyle
为了自定义现有样式,需要继承QProxyStyle并重新实现所需的虚函数。QProxyStyle允许指定某个基本样式,当基本样式未指定时,将自动使用应用程序样式。前者提供对基本样式的完全控制,并且在自定义需要特定样式行为时效果最佳,而后者提供一种与平台无关的方式来自定义默认为本机平台样式的应用程序样式。

class Q_WIDGETS_EXPORT QProxyStyle : public QCommonStyle{};

QCommonStyle
QCommonStyle为完全自定义样式实现提供了一个方便的基类。这种方式与使用QProxyStyle相同,但是继承自QCommonStyle并重新实现相应的虚函数。

class Q_WIDGETS_EXPORT QCommonStyle: public QStyle{};

QStyle实现
QStyle的API包含绘制控件的函数,用于执行常见和困难任务的静态函数以及用于执行绘制时所需的各种计算的函数。该样式也辅助控件内容的布局,此外还创建一个包含QBrush的QPalette对象。

QStyle绘制图形元素,一个元素是一个控件,或者是一个控件部分(如按钮斜角、窗口框架或滚动条等等)。大多数绘制函数采用四个函数:

  • 枚举值指定绘制元素的类型;
  • QStyleOption对象指定呈现该元素的方式和位置;
  • QPainter对象表示执行绘图的画笔;
  • QWidget对象表示执行绘图的控件。

当控件要求样式绘制元素时,控件会为样式提供QStyleOption对象(包含绘制所需信息的类)。QStyleOption类使得可以在不链接控件代码的情况下绘制控件,从而在任何绘画设备上使用QStyle的绘制函数成为可能。在Qt中,Item Views的items由委托绘制。Item Views的标题任由样式绘制。

样式元素
样式元素是GUI的图形部分。一个控件由样式元素的层次结构(或树)组成。比如,当样式收到绘制按钮的请求时(例如,从QPushButton),样式会绘制一个标签(文本和图标)、一个按钮斜角和一个焦点框。而按钮斜角由斜角周围的框架和另外两个元素组成。

请添加图片描述
绘制控件不一定是通过要求样式只绘制一个元素来完成,控件可以多次调用来绘制不同元素。比如QTabWidget单独绘制选项卡和框架。

元素类型分三种:基本元素、控制元素和复杂控制元素,元素由枚举类型ComplexControl、ControlElement和PrimitiveElement enums定义。

  • 基本元素:

基本元素是常见的GUI元素。例如,框架frame、按钮斜角button bavels以及用于输入框spin boxes、滑动条scroll bars和下拉框combo boxes的箭头。基本元素不能独立存在,而是整体结构的一部分,不参与用户交互,而是GUI中的被动装饰。

  • 控制元素:

控制元素执行操作或者向用户显示信息。控制元素包括表和树视图中的按钮、勾选框和标题部分。控制元素不一定是完整的小部件,也可以是控件的部分结构,比如滑动条滑块和选项卡。控制元素与基本元素的不同之处在于其不是被动的,而是在交互中填充功能。有多个元素组成的控件通常使用样式来计算元素的边界矩形,可用的子元素由枚举类型SubElement定义。此枚举仅用于计算边界矩形,子元素不是像基本元素、控制元素和复杂元素那样需要绘制的图形元素。

  • 复杂的控制元素:

复杂的控制元素包含子控件。复杂控件的行为会有所不同,具体取决于用户使用鼠标的位置和按下的键盘键。这取决于鼠标处于或按键按下的子控件(如果有)。复杂控件元素有滚动条和组合框。可以通过鼠标移动滑动块或者按向上和向下按钮来使用滑动条。可用的子控件由枚举SubControl枚举类型定义。

除了绘图之外,样式还需要为控件提供有关鼠标在哪个子控件上进行操作的信息。例如,互动条需要知道用户是否按下滑块、滑块凹槽或向上、向下按钮。

和控制元素不同,不能使用样式绘制子控件,样式仅计算应在其中绘制子控件的边界矩形。然而,复杂元素通常使用控制元素和基本元素来绘制子控件。

样式选项
QStyleOption的子类包含设置各个元素样式所需的所有信息。样式选项通常在栈上被实例化,并由QStyle函数的调用方填写。根据绘制的内容,样式期望不同的样式选项类。例如,QStyle::PE_FrameFocusRect元素需要一个QStyleOptionFocusRect参数,并且可以创建一个自定义样式可以使用的自定义子类。出于性能原因,样式选项保留公共变量

控件可以处于许多不同的状态,这些状态由State枚举类型定义。根据控件的不同,状态标志具有不同的含义,但像State_Disabled这样的状态标志对所有控件都是通用的。

最值得注意的是,样式选项包含要绘制的控件的调色板和边界矩形,大多数控件都有专门的样式选项,例如QPushButton和QCheckBox使用QStyleOptionButton用作样式选项,其中包含文本、图标及其图标的大小。

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

QStyle函数
定义了三个虚函数,用来绘制基本元素、控制元素和复杂控制元素。

  • 绘制基本元素drawPrimitive
  • 绘制复杂控制元素drawComplexControl
  • 绘制控制元素drawControl

QStyle类还提供绘制元素时使用的辅助函数,drawItemText函数在指定的矩形内绘制文本,将调色板对象作为参数。drawItemPixmap函数在指定的边界矩形内对齐像素图。

其它QStyle函数为执行绘制的函数进行各种计算。如果控件绘制多个样式元素,也使用这些函数来计算大小提示和边界矩形。和绘制元素的函数一样,辅助函数通常采用相同的参数。

  • subElementRect函数采用SubElement枚举值并计算子元素的边界矩形,样式使用此函数来得到绘制元素不同部分的位置。
  • subControlRect函数用来计算复杂控制元素中的子控件的边界矩形,实现新样式时需要重新实现该函数并计算矩形。
  • pixelMetric函数返回像素度量,该指标是以屏幕像素为单位给出的与样式相关的大小。采用PixelMetric枚举值并返回正确的测量值。
  • hitTestComplexControl函数返回鼠标指针在复杂控制元素中的子控件上。

QStyle还定义了函数polish和unpolish函数,所有控件在显示之前都会被发送到polish函数,在隐藏时会被发送到unpolish。可以使用这些函数在设置控件上的属性,或者执行样式所需的其它工作。例如,如果需要知道鼠标何时悬停在控件上,需要设置WA_Hover属性,然后控件中的样式选项中的State_MouseOver状态位被设置。

QStyle也定义了一些静态辅助函数,执行一些常见但困难的任务。例如,根据滑块的值计算滑块手柄的位置,并转换矩形并绘制文本,考虑反向布局。

调色板
QPalette提供调色板,存储不同控件状态和颜色角色的颜色。每种样式都提供调色板应用于控件的绘制。有一组颜色集合对应于不同的控件状态:活动状态(具有焦点)、非活动状态和禁用状态。可以通过查询State_Enabled和State_Actived状态标志得到当前的状态。每一个颜色集合包含由枚举类型QPalette::ColorRole确定的颜色职责。这些职责描述了在一种情况(绘制控件背景、文本和按钮)下应该使用对应的颜色。

如何使用颜色职责取决于样式,例如,如果样式使用渐变,则可以使用使用QColor::darked或QColor::lighter使其更暗或更亮从而创建渐变。如果需要调色板没有提供的画布,通常应该继承。

Java风格
实现一种类似于Java默认外观的样式。

设计与实现
设计样式的第一步是选择基类,通常选择继承QCommonStyle,该类实现了需要的大多数功能,而不是执行实际的绘图。

改样式在一个类中实现。

尝试实现一个控件

公共的控件属性和变量

某些状态和变量对于所有控件来说是通用的,这些属性通过QStyleOption::initFrom函数设置。并非所有元素都使用该函数。

状态状态设置条件
State_Enabled控件没有禁用时
State_Focus控件有焦点
State_KeyboardFocusChange键盘焦点更改
State_MouseOver鼠标在控件上
State_Active控件是活动窗口的子窗口
State_HasEditFocus控件具有编辑焦点
变量内容
rect绘制元素的边界矩形
direction布局方向
palette绘制元素使用的调色板
fontMetrics绘制文本的字体计量

QPushButton

按钮的样式结构图下所示,通过对树进行自上而下的遍历,可以获得绘制元素的顺序。
请添加图片描述
按钮的布局(和元素边界相关)因样式而异。元素可能有相同的边界。例如,PE_PushButtonBevel被用于在QCommonStyle中绘制三个元素:PE_FrameDefaultButton、PE_FrameButtonBevel和PE_PanelButtonCommand,这些元素在公共样式中具有相同的边界。

下面给出了一个按钮图像,该图像显示了元素的边界矩形。颜色用于分隔图像中的边界矩形。
请添加图片描述
QPushButton的样式选项是QStyleOptionButton,QPushButton可以在样式选项上设置的状态表如下。

状态状态设置条件
State_Sunken按钮按下或按下菜单显示
State_On按钮被选中
State_Raised按钮没按下也没升起
成员变量内容
features描述各种按钮属性
icon按钮图标
iconSizeicon的大小
text按钮文本

QCheckBox和QRadioButton

QCheckBox和QRadioButton的结构是相同的。
请添加图片描述

状态状态设置条件
State_Sunken框被按下
State_NoChange框被部分选中
State_On框被选中
State_Off按钮没按下也没升起

Tabs选项卡

在Qt中,QTabBar使用样式来绘制选项卡。选项卡要么存在于包含QTabBar的QTabWidget,要么作为单独的选项卡栏存在。

QTabBar和QTabWidget的样式结构如下。
请添加图片描述
tab bar形状和标签具有与CE_TabBarTab相同的边界矩形。请注意,tabs和tab widget框架重叠,tab bar的底部是重叠的区域。

tabs的样式QStyleOptionTab包含绘制tabs必须的信息。该样式选项包含tab在tab bar中的位置,选择tab的位置,tab的形状,文本,图标和图标的大小。
请添加图片描述
tab bar可以在tabs上设置的状态表如下。

状态状态设置条件
State_Sunken选项卡被鼠标选中
State_Selected是当前选项卡
State_HasFocus选项卡栏具有焦点且选项卡处于选中状态

QStyleOptionTab的成员表如下。

成员变量内容
cornerWidgets指示tab bar是否具有角控件以及具有哪些角控件
icontab图标
iconSizeicon的大小
texttab文本
positiontab在tab bar上相对于其它tab的位置
rowtab所在的行
selectedPosition指示所选tab和tab相邻还是tab
shape指示tab是圆角还是三角以及tab的方向

tab widget的外框使用QStyleOptionTabWidgetFrame作为样式选项,除了通用的标志外,没有其它状态标志。

成员变量内容
cornerWidgets指示tab bar是否具有角控件以及具有哪些角控件
icontab图标
iconSizeicon的大小
texttab文本
positiontab在tab bar上相对于其它tab的位置
rowtab所在的行
selectedPosition指示所选tab和tab相邻还是tab
shape指示tab是圆角还是三角以及tab的方向

Scroll Bars
请添加图片描述
QScrollBar只需创建样式选项,然后绘制控件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值