34. QPainter绘图技术
一、QPainter绘图
绘图是指在绘图设备(窗口、控件、图像、打印机等)上将用户构思出的图形绘制出来,图形包括点、线、矩形、多边形、椭圆、文字及保存到磁盘上的图像等。可以对绘制的图形进行处理,如给封闭的图形填充颜色。
绘图设备是从 QPaintDevice 继承的类,包括继承自 QWidget 的窗口、各种控件、QPixmap 和 QImage。如果绘图设备是窗口或控件,则 QPainter 绘图一般放到 paintEvent() 事件或者被 paintEvent() 事件调用的函数中。
我们可以在终端中使用 pip 安装 PySide6 模块。默认是从国外的主站上下载,因此,我们可能会遇到网络不好的情况导致下载失败。我们可以在 pip 指令后通过 -i 指定国内镜像源下载。
pip install pyside6 -i https://mirrors.aliyun.com/pypi/simple
国内常用的 pip 下载源列表:
- 阿里云 https://mirrors.aliyun.com/pypi/simple
- 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple
- 中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple
用 QPainter 类创建绘图实例的方法如下:
QPainter()
QPainter(device=QPaintDevice)
其中 QPaintDevice 是指继承自 QPaintDevice 的绘图设备。如果使用不带设备的 QPainter() 方法创建实例对象,,则在开始绘图前需要用 painter.begin(device:QPaintDevice) 方法 指定绘图设备,此时 painter.isActive() 的返回值是 True,绘图完成后,需要用 painter.end() 方法 声明完成绘图,之后可以用 begin() 方法 重新指定绘图设备。begin() 和 end() 方法都返回 bool 值。
QPainter 类常用对状态进行设置的方法如下:
# 设置背景色,背景色只对不透明的文字、虚线或位图起作用
setBackground(bg:Union[QBursh, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradient, QImage, QPixmap]) -> None
setBackgroundMode(mode:Qt.BGMode) -> None # 设置透明或不透明背景模式
setFont(f:Union[QFont, str, Sequence[str]]) -> None # 设置字体
setLayoutDirection(direction:Qt.LayoutDirection) -> None # 设置布局方向
setOpacity(opacity:float) -> None # 设置不透明度
# 设置画刷
setBrush(brush:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradient, QImage, QPixmap]) -> None
setBrush(style:Qt.BrushStyle) -> None # 设置画刷
setBrushOrigin(origin:Union[QPointF, QPoint, QPainterPath.Element]) -> None # 设置画刷的起点
setBrushOrigin(x:int, y:int) -> None # 设置画刷的起点
setPen(pen:Union[QPen, Qt.PenStyle, QColor]) -> None # 设置钢笔
setPen(color:Union[QColor, Qt.GlobalColor, str]) -> None # 设置钢笔
setClipPath(path:QPainterPath, op:Qt.ClipOperation=Qt.ReplaceClip) -> None # 设置剪切路径
setClipRect(rect:QRect, op:Qt.ClipOperation=Qt.ReplaceClip) -> None # 设置剪切矩形区域
setClipRect(arg_1:Union[QRectF, QRect], op:Qt.ClipOperation=Qt.ReplaceClip) -> None # 设置剪切矩形区域
setClipRect(x:int, y:int, w:int, h:int, op:Qt.ClipOperation=Qt.ReplaceClip) -> None # 设置剪切矩形区域
setClipRegion(arg__1:Union[QRegion, QBitmap, QPolygon, QRect], op=Qt.ReplaceClip) -> None # 设置剪切区域
setClipping(enable:bool) -> None # 设置是否启动剪切
setCompositionMode(mode:QPainter.CompositionMode) -> None # 设置图形的合成模式
setRenderHint(hint:QPainter.RenderHint, on:bool=true) -> None # 设置渲染模式
setRenderHints(hints:QPainter.RenderHints, on:bool=true) -> None # 设置多个渲染模式
setTransform(transform:QTransform, combine:bool=false) -> None # 设置全局变化矩阵
setWorldTransform(matrix:QTransform, combine:bool=false) -> None # 设置全局变化矩阵
setViewTransformEnabled(enable:bool) -> None # 设置是否启动视图变换
setViewport(viewport:QRect) -> None # 设置视口
setViewport(x:int, y:int, w:int, h:int) -> None # 设置视口
setWindow(window:QRect) -> None # 设置逻辑窗口
setWindow(x:int, y:int, w:int, h:int) -> None # 设置逻辑窗口
setWorldMatrixEnabled(enabled:bool) -> None # 设置是否启动全局矩阵变换
save() -> None # 保存状态到堆栈中
restore() -> None # 从堆栈中恢复状态
二、设置钢笔
钢笔 QPen 用于 绘制线条,线条有样式(实线、虚线、点虚线)、颜色、宽度等属性,用 QPainter 的 setPen(QPen) 方法为 QPainter 设置钢笔。
QPen()
QPen(style:Qt.PenStyle)
QPen(color:Union[QColor, Qt.GlobalColor, str, int])
QPen(pen:Union[QPen, Qt.PenStyle, QColor])
QPen(brush:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradient, QImage, QPixmap], width:float, style:Qt.PenStyle=Qt.PenStyle.SolidLine, c:Qt.PenCapstyle=Qt.PenCapstyle.SquareCap, j:Qt.PenJoinstyle=Qt.PenJoinstyle.BevelJoin)
参数 style 用于 设置钢笔的样式,它是 Qt.PenStyle 的枚举值,可以取值如下:
Qt.PenStyle.NoPen # 不绘制线条
Qt.PenStyle.SolidLine # 实线
Qt.PenStyle.DashLine # 虚线
Qt.PenStyle.DotLine # 点线
Qt.PenStyle.DashDotLine # 点画线
Qt.PenStyle.DashDotDotLine # 双点划线
Qt.PenStyle.CustomDashLine # 自定义线

参数 c 用于 设置线条端点样式,它是 Qt.PenCapStyle 的枚举值,可以取值如下:
Qt.PenCapStyle.FlatCap # 不包含端点
Qt.PenCapStyle.SquareCap # 包含端点
Qt.PenCapStyle.RoundCap # 包含端点,并延长半个宽度

参数 j 用于 设置线条连接点处的样式,它是 Qt.PenJoinStyle 的枚举值,可以取值如下:
Qt.PenJoinStyle.MiterJoin
Qt.PenJoinStyle.BevelJoin
Qt.PenJoinStyle.RoundJoin
Qt.PenJoinStyle.SvgMiterJoin

钢笔默认的 颜色 是 黑色,宽度 是 1 像素,样式 是 实线,端点样式 是
Qt.SquareCap,连接处 是Qt.BevelJoin。
QPen 类的常用方法如下:
setStyle(style:Qt.PenStyle) -> None # 设置线条样式
style() - Qt.PenStyle # 获取线条样式
setWidth(width:int) -> None # 设置线条宽度
setWidth(width:float) -> None # 设置线条宽度
isSolid() -> bool # 获取线条样式是否是实现填充
setBrush(brush:Union[QBrush, Qt.BrushStyle, QColor, Qt.GlobalColor, QGradient, QImage, QPixmap]) -> None # 设置画刷
brush() -> QBrush # 获取画刷
setCapStyle(style:Qt.PenCapStyle) -> None # 设置线端部的样式
capStyle() -> Qt.PenCapStyle # 获取线端部的样式
setColor(color:Union[QColor, Qt.GlobalColor, str, int]) -> None # 设置颜色
color() -> QColor # 获取颜色
setCosmetic(cosmetic:bool) -> None # 设置是否进行装饰
isCosmetic() -> bool # 获取是否进行装饰
setDashOffset(doffset:float) -> None # 设置虚线开始绘制的点与线起始点的距离
setDashPattern(pattern:Sequence[float]) -> None # 设置用户自定义虚线样式
setJoinStyle(style:Qt.PenJoinStyle) -> None # 设置两相交线连接点出的样式
setMiterLimit(length:float) -> None # 设置斜接延长线的长度
线条的宽度 用 setWidth(width:int) 或 setWidthF(width:float) 方法设置,如果宽度始终为 0,表示是 装饰线条。装饰线条 也可用 setCosmetic(bool) 方法设置。装饰线条 是指具有恒定宽度的边,可确保线条在不同缩放比例下具有相同的宽度。线条的样式 用 setStyle(Qt.PenStyle) 方法设置。钢笔的端点样式 用 setCapStyle(Qt.PenCapStyle) 方法设置。两个线条连接点处的样式 用 setJoinStyle(Qt.PenJoinStyle) 方法设置。
如果线条连接样式是 Qt.PenJoinStyle.MiterJoin 时,用 setMiterLimit(widht:float) 方法 设置延长线的长度,其中参数 width 是 线条宽度的倍数,默认是2.0,其延长线的含义如下所示。

用 setDashPattern(Sequence[float]) 方法可以 自定义虚线样式,其中参数的 奇数项表示实线的长度,偶数项表示空白处的长度,长度以线宽为单位,表示为线宽的倍数。
用 setDashOffset(distance:float) 方法可以 设置虚线开始绘制的点与线起始点之间的距离,如果这个距离是动态的,则会形成动画效果。
新建一个 template.py 文件。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QPointF, Qt
from PySide6.QtGui import QPainter, QPaintEvent, QPen
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建画笔对象
pen.setColor(Qt.GlobalColor.blue) # 3.设置线条颜色
pen.setWidth(10) # 4.设置线条宽度
pen.setStyle(Qt.PenStyle.DashDotDotLine) # 5.设置线条样式
pen.setCapStyle(Qt.PenCapStyle.RoundCap) # 6.设置线条连接点处的样式
pen.setJoinStyle(Qt.PenJoinStyle.RoundJoin) # 7.设置线条连接处样式
painter.setPen(pen) # 8.设置画笔对象
p1 = QPointF(50, 50)
p2 = QPointF(self.width() - 50, 50)
p3 = QPointF(50, self.height() - 50)
p4 = QPointF(self.width() - 50, self.height() - 50)
painter.drawPolyline([p1, p2, p3, p4]) # 9、绘制一条折线
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
三、设置画刷
对于封闭的图形,如矩形、圆等,用画刷 QBrush 可以在其内部填充颜色、样式、渐变、纹理或图案。用 QBrush 类创建画刷的方法如下所示。
QBrush()
QBrush(style:Qt.BrushStyle)
QBrush(brush:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradient, QImage, QPixmap])
QBrush(color:Qt.GlobalColor, bs:Qt.BrushStyle=Qt.SolidPattern)
QBrush(color:Qt.GlobalColor, pixmap:Union[QPixmap, QImage, str])
QBrush(color:Union[QColor, Qt.GlobalColor, str], bs:Qt.BrushStyle=Qt.SolidPattern)
QBrush(color:Union[QColor, Qt.GlobalColor, str], pixmap:Union[QPixmap, QImage, str])
QBrush(gradient:Union[QGradient, QGradient.Preset])
QBrush(image:Union[QImage, str])
QBrush(pixmap:Union[QPixmap, QImage, str])
QBrush 类的常用方法如下:
setStyle(style:Qt.BrushStyle) -> None # 设置风格
style() -> Qt.BrushStyle # 获取风格
setTexture(pixmap:QPixmap) -> None # 设置纹理图片
texture() -> QPixmap # 获取纹理图片
setTextureImage(image:QImage) -> None # 设置纹理图片
textureImage() -> QImage # 获取纹理图片
setColor(color:Union[QColor, Qt.GlobalColor, str]) -> None # 设置颜色
color() -> QColor # 获取颜色
gradient() -> QGradient # 获取渐变色
setTransform(matrix:QTransform) -> None # 设置变换矩阵
transform() -> QTransform # 获取变换矩阵
isOpaque() -> bool # 设置是否不透明
画刷的风格 用 setStyle(style:Qt.BrushStyle) 方法设置,其中参数 style 是 Qt.BrushStyle 类型的枚举值,可以取值如下所示:
Qt.BrushStyle.SolidPattern
Qt.BrushStyle.Dense1Pattern
Qt.BrushStyle.Dense2Pattern
Qt.BrushStyle.Dense3Pattern
Qt.BrushStyle.Dense4Pattern
Qt.BrushStyle.Dense5Pattern
Qt.BrushStyle.Dense6Pattern
Qt.BrushStyle.Dense7Pattern
Qt.BrushStyle.HorPattern
Qt.BrushStyle.VerPattern
Qt.BrushStyle.CrossPattern
Qt.BrushStyle.BDiagPattern
Qt.BrushStyle.FDiagPattern
Qt.BrushStyle.DiagCrossPattern
Qt.BrushStyle.TexturePattern
Qt.BrushStyle.NoBrush

画刷的纹理 可以用 setTexture(texture:QPixmap) 或 setTextureImage(texture:QImage) 方法来设置,这时 画刷的样式 被设置成 Qt.BrushStyle.TexturePattern。
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QPointF, QRectF, Qt
from PySide6.QtGui import QPainter, QPaintEvent, QBrush
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
brush = QBrush() # 2.创建画刷对象
brush.setColor(Qt.GlobalColor.blue) # 3.设置画刷颜色
brush.setStyle(Qt.BrushStyle.CrossPattern) # 4.设置画刷样式
painter.setBrush(brush) # 5.设置画刷
p1 = QPointF(self.width() / 4, self.height() / 4)
p2 = QPointF(3 * self.width() / 4, 3 * self.height() / 4)
painter.fillRect(QRectF(p1, p2), brush) # 6.填充一个矩形
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
四、渐变色
在用画刷进行填充时,可以设置填充颜色为渐变色。所谓渐变色是指在两个不重合的点处分别设置不同的颜色,这两个点一个是起点,另一个是终点,这两个点之间的颜色从起点的颜色逐渐过渡到终点的颜色。
定义渐变色的类是 QGradient,渐变样式分为 3 种类型,分别为 线性渐变 QLinearGradient、径向渐变 QRadialGradient 和 圆锥渐变 QConicalGradient,它们都继承自 QGradient 类,也会继承 QGradient 类的属性和方法。

QLinearGradient、QRadialGradient 和 QConicalGradient 继承自 QGradient,因此也会继承 QGradient 的方法。QGradient 类的常用方法如下:
setCoordinateMode(mode:QGradient.CoordinateMode) -> None # 设置坐标模式
coordinateMode() -> QGradient.CoordinateMode # 获取坐标模式
setColorAt(position:float, color:Union[QColor, Qt.GlobalColor, str]) -> None # 设置颜色
setStops(stops:Sequence[Tuple[float, QColor]]) -> None # 设置颜色
setInterpolationMode(mode:QGradient.InterpolationMode) -> None # 设置插值模式
interpolationMode() -> QGradient.InterpolationMode # 获取插值模式
setSpread(spread:QGradient.Spread) -> None # 设置扩展模式
spread() -> QGradient.Spread # 获取扩展模式
type() -> QGradient.Type # 获取类型
在渐变区域内,可以在多个点设置颜色值,这些点之间的颜色值根据两侧的颜色来确定。在定义内部点的颜色值时,通常通过逻辑坐标来定义,渐变区域内的起始点的逻辑值是 0,终止点的逻辑值是 1。如果要在中间位置定义颜色,可以用 setColorAt(pos:float, color:Union[QColor, Qt.GlobalColor, str]) 方法来定义。我们也可以用 setStops(stops:Sequence[Tuple[float, QColor]]) 方法一次定义多个颜色值。
用 setCoordinateMode(mode:QGradient.CoordinateMode) 方法可以设置坐标的模式,参数 QGradient.CoordinateMode 的取值如下所示:
# 逻辑方式,起始点为0,终止点为1,这是默认值
QGradient.CoordinateMode.LogicalMode
# 相对于绘图区域矩形边界的逻辑坐标,左上角的坐标是(0, 0),右下角的坐标是(1, 1)
QGradient.CoordinateMode.ObjectMode
# 相对于绘图设备矩形边界的逻辑坐标,左上角的坐标是(0, 0),右下角的坐标是(1, 1)
QGradient.CoordinateMode.StretchToDeviceMode
# 与ObjectMode基本相同,除了QBrush.transform()应用与逻辑空间而不是物理空间
QGradient.CoordinateMode.ObjectBoundingMode
当设置的渐变区域小于填充区域时,渐变颜色可以扩展到渐变区域以外的空间。扩展模式用 setSpread(spread:QGradient.Spread) 方法定义,参数 spread 是 QGradient.Spread 类型的枚举值,可以取值如下所示:
QGradient.Spread.PadSpread # 用最近的颜色扩展
QGradient.Spread.RepeatSpread # 重复渐变
QGradient.Spread.ReflectSpread # 对称渐变
扩展模式不适合圆锥渐变,圆锥渐变没有固定的边界。
用 setInterpolationMode(mode:QGradient.InterpolationMode) 方法 设置渐变色内部的插值模式,参数 mode 是 QGradient.InterpolationMode 类型的枚举值,可以取值如下:
QGradient.InterpolationMode.ColorInterpolation
QGradient.InterpolationMode.ComponentInterpolation
用 type() 方法可以 获取渐变类型,返回值可能如下:
QGradient.Type.LinearGradient # 线性渐变
QGradient.Type.RadialGradient # 径向渐变
QGradient.Type.ConicalGradient # 圆锥渐变
QGradient.Type.NoGradient # 无渐变色
4.1、线性渐变
用 QLinearGradient 类创建线性渐变色的方法如下所示。
QLinearGradient()
QLinearGradient(xStart:float, yStart:float, xFinalStop:float, yFinalStop:float)
QLinearGradient(start:Union[QPointF, QPoint, QPainterPath.Element], finalStop:Union[QPointF, QPainterPath.Element])
线性渐变 需要一个 线性渐变矩形区域(起始和终止位置),参数用于确定这个矩形区域。
QLinearGradient 类的常用方法:
setStart(start:Union[QPontF, QPoint, QPainterPath.Element]) -> None # 设置起始点
setStart(x:float, y:float) -> None # 设置起始点
start() -> QPointF # 获取起始点
setFinalStop(stop:Union[QPontF, QPoint, QPainterPath.Element]) -> None # 设置终止点
setFinalStop(x:float, y:float) -> None # 设置终止点
finalStop() -> QPointF # 获取终止点
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QPointF, QRectF, Qt
from PySide6.QtGui import QPainter, QPaintEvent, QPen, QBrush
from PySide6.QtGui import QLinearGradient
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
width = self.width()
height = self.height()
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建钢笔对象,绘制边框
pen.setWidth(5) # 3.设置边框宽度
pen.setColor(Qt.GlobalColor.darkBlue) # 4.设置边框颜色
pen.setStyle(Qt.PenStyle.DashLine) # 5.设置边框样式
painter.setPen(pen) # 6.设置钢笔
linear = QLinearGradient(QPointF(0, 0), QPointF(width / 4, height / 4)) # 7.线性渐变
# 8.设置颜色
linear.setStops([(0, Qt.GlobalColor.red), (0.3, Qt.GlobalColor.yellow), (0.6, Qt.GlobalColor.green), (1, Qt.GlobalColor.blue)])
linear.setSpread(QLinearGradient.Spread.ReflectSpread) # 9.设置扩展模式
brush = QBrush(linear) # 10.用线性渐变定义画刷
painter.setBrush(brush) # 11.设置画刷
painter.drawRect(QRectF(0, 0, width, height)) # 12.绘制矩形
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
4.2、径向渐变
用 QRadialGradient 类创建径向渐变色的方法如下:
QRadialGradient()
QRadialGradient(cx:float, cy:float, radius:float)
QRadialGradient(center:Union[QPointF, QPoint, QPainterPath.Element], radius:float)
QRadialGradient(cx:float, cy:float, radius:float, fx:float, fy:float)
QRadialGradient(center:Union[QPointF, QPoint, QPainterPath.Element], radius:float, focalPoint:Union[QPointF, QPoint, QPainterPath.Element])
QRadialGradient(cx:float, cy:float, centerRadius:float, fx:float, fy:float, focalRadius:float)
QRadialGradient(center:Union[QPointF, QPoint, QPainterPath.Element], centerRadius:float, focalPoint:Union[QPointF, QPoint, QPainterPath.Element], focalRadius:float)
QRadialGradient 类的常用方法:
setCenter(center:Union[QPointF, QPoint]) -> None # 设置圆心
setCenter(x:float, y:float) -> None # 设置圆心
setRadius(radius:float) -> None # 设置半径
setCenterRadius(radius:float) -> None # 设置半径
setFocalPoint(focalPoint:Union[QPointF, QPoint, QPainterPath.Element]) -> None # 设置焦点位置
setFocalPoint(x:float, y:float) -> None # 设置焦点位置
setFocalRadius(radius:float) -> None # 设置焦点半径
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QPointF, QRectF, Qt
from PySide6.QtGui import QPainter, QPaintEvent, QPen, QBrush
from PySide6.QtGui import QRadialGradient
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
width = self.width()
height = self.height()
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建钢笔对象,绘制边框
pen.setWidth(5) # 3.设置边框宽度
pen.setColor(Qt.GlobalColor.darkBlue) # 4.设置边框颜色
pen.setStyle(Qt.PenStyle.DashLine) # 5.设置边框样式
painter.setPen(pen) # 6.设置钢笔
radial = QRadialGradient(QPointF(width / 2, height / 2), width / 8) # 7.径向渐变
# 8.设置颜色
radial.setColorAt(0, Qt.GlobalColor.red)
radial.setColorAt(0.3, Qt.GlobalColor.yellow)
radial.setColorAt(0.6, Qt.GlobalColor.green)
radial.setColorAt(1, Qt.GlobalColor.blue)
radial.setSpread(QRadialGradient.Spread.RepeatSpread) # 9.设置扩展模式
brush = QBrush(radial) # 10.用径向渐变创建画刷
painter.setBrush(brush) # 11.设置画刷
painter.drawRect(QRectF(0, 0, width, height)) # 12.绘制矩形
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
4.3、圆锥渐变
径向渐变 需要的几何参数下所示,需要确定 圆心位置、半径、焦点位置 和 焦点半径。径向渐变的构造函数中,参数 center 是 圆心位置,可以用点或坐标定义。参数 centerRadius 是 半径;第 focalPoint 个参数是 焦点位置,可以用点或坐标定义;第 focalRadius 个参数是 焦点半径。如果焦点设置到圆的外面,则取圆上的点作为焦点。
用 QConicalGradient 创建 圆锥渐变色 的方法如下所示:
QConicalGradient()
QConicalGradient(cx:float, cy:float, startAngle:float)
QConicalGradient(center:Union[QPointF, QPoint, QPainterPath.Element], startAngle:float)
圆锥渐变 需要的几何参数为 圆心位置 和 起始角度 a,角度必须在 0°~360° 之间,圆心位置可以用点或坐标来定义。

QConicalGradient 类的常用方法:
setCenter(center:Union[QPointF, QPoint]) -> None # 设置圆心
setCenter(x:float, y:float) -> None # 设置圆心
setAngle(angle:float) -> None # 设置起始角度
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QPointF, QRectF, Qt
from PySide6.QtGui import QPainter, QPaintEvent, QPen, QBrush
from PySide6.QtGui import QConicalGradient
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
width = self.width()
height = self.height()
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建钢笔对象,绘制边框
pen.setWidth(5) # 3.设置边框宽度
pen.setColor(Qt.GlobalColor.darkBlue) # 4.设置边框颜色
pen.setStyle(Qt.PenStyle.DashLine) # 5.设置边框样式
painter.setPen(pen) # 6.设置钢笔
conical = QConicalGradient(QPointF(width / 2, height / 2), height / 8) # 7.圆锥渐变
conical.setAngle(60) # 8.设置开始角度
# 9.设置颜色
conical.setColorAt(0, Qt.GlobalColor.red)
conical.setColorAt(0.3, Qt.GlobalColor.yellow)
conical.setColorAt(0.6, Qt.GlobalColor.green)
conical.setColorAt(1, Qt.GlobalColor.blue)
brush = QBrush(conical) # 10.创建画刷
painter.setBrush(brush) # 11.设置画刷
painter.drawRect(QRectF(0, 0, width, height)) # 12.绘制矩形
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
五、绘制几何图形
5.1、绘制点
QPainter 可以一次绘制一个点,也可以一次绘制多个点,其中 QPolygon 和 QPolygonF 是用于存储多个 QPoint 和 QPointF 的类。
# 绘制单点
drawPoint(x:int, y:int) -> None
drawPoint(p:QPoint) -> None
drawPoint(pt:Union[QPointF, QPoint]) -> None
drawPoint(pt:QPainterPath.Element) -> None
# 绘制多点
drawPoints(points:Sequence[QPointF]) -> None
drawPoints(points:Sequence[QPoint]) -> None
drawPoints(points:Union[QPolygon, Sequence[QPoint], QRect])
drawPoints(points:Union[QPolygon, Sequence[QPoint], QPolygon, QRectF])
创建 QPolygon 实例的方法如下:
QPolygon()
QPolygon(points:Sequence[QPoint])
创建 QPolygonF 实例的方法如下:
QPolygonF()
QPolygonF(points:Sequence[Union[QPointF,QPoint]])
用 QPolygon 的 append(point:QPoint) 方法可以 添加点,用 insert(pos:int,point:QPoint) 方法可以 插入点,用 setPoint(pos:int,point:QPoint) 方法可以 更改点。用 QPolygonF 的 append(point:Union[QPointF,QPoint]) 方法可以 添加点,用 insert(pos:int, point:Union[QPointF,QPoint]) 方法可以 插入点。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QPointF
from PySide6.QtGui import QPainter, QPaintEvent, QPen
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建钢笔对象
pen.setColor("red") # 3.设置钢笔的颜色
pen.setWidth(10) # 4.设置钢笔的宽度
painter.setPen(pen) # 5.设置钢笔
painter.drawPoint(QPointF(self.width() / 2, self.height() / 2)) # 6.绘制点
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
5.2、绘制直线
绘制直线需要用两个点。可以一次绘制一条直线,也可一次绘制多条直线,其中 QLine 或 QLineF 是 2D 直线类。
# 绘制单条直线
drawLine(line:QLine) -> None
drawLine(line:Union[QLineF, QLine]) -> None
drawLine(p1:QPoint, p2:QPoint) -> None
drawLine(p1:Union[QPointF, QPoint], p2:Union[QPointF, QPoint]) -> None
drawLine(x1:int, y1:int, x2:int, y2:int) -> None
# 绘制多条直线
drawLines(lines:Sequence[QLine]) -> None
drawLines(lines:Sequence[QLineF]) -> None
drawLines(pointPairs:Sequence[QPoint]) -> None
drawLines(pointPairs:Sequence[QPointF]) -> None
用 QLine 类定义直线实例的方法如下:
QLine()
QLine(p1:QPoint, p2:QPoint)
QLine(x1:int, y1:int, x2:int, y2:int)
用 QLineF 类定义直线实例的方法如下:
QLineF()
QLineF(line:QLine)
QLineF(p1:Union[QPointF,QPoint], p2:Union[QPointF,QPoint])
QLineF(x1:float, y1:float, x2:float, y2:float)
用 QLine 的 setLine(x1:int, y1:int, x2:int, y2:int) 方法、setP1(point:QPoint) 方法、setP2(point:QPoint) 或 setPoints(p1:QPoint, p2:QPoint) 方法可以 设置线两端的点。QLineF 也有同样的方法,只需把参数 int 改成 float,或 QPoint 改成 QPointF。
在绘制几何图像和文字时,如果线条是斜线,对线条进行放大后会发现它呈现锯齿状。为防止出现锯齿状,需要对线条边缘进行模糊化处理。用 QPainter 的 setRenderHint(hint:QPainter.RenderHint, on:bool=True) 或 setRenderHints(hints:QPainter.RenderHints, on:bool=True) 方法可以 设置是否进行抗锯齿处理,用 testRenderHint(hint:QPainter.RenderHint) 方法可以 获取是否设置了抗锯齿算法,其中参数 hind 是 QPainter.RenderHint 类型的枚举值,可以取值如下:
QPainter.RenderHint.Antialiasing # 启用抗锯齿
QPainter.RenderHint.TextAntialiasing # 对文本进行抗锯齿
QPainter.RenderHint.SmoothPixmapTransform # 使用平滑的像素图像算法
QPainter.RenderHint.LosslessImageRendering # 用于PDF文档
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QPointF
from PySide6.QtGui import QPainter, QPaintEvent, QPen
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建画笔对象
pen.setColor("red") # 3.设置钢笔的颜色
pen.setWidth(10) # 4.设置画笔宽度
painter.setPen(pen) # 5.设置绘图对象画笔
painter.drawLine(QPointF(0, 0), QPointF(self.width(), self.height())) # 6.绘制直线
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) # 7.抗锯齿
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
5.3、绘制折线
绘制折线必须用两个点,即使两条折线的终点和起始点相同,每条折线也必须用两个点来定义。折线由多个折线段构成,绘制折线需要给出多个点,上个折线段的终点是下个折线段的起始点。
drawPolyline(points:Sequence[QPoint]) -> None
drawPolyline(points:Sequence[QPointF]) -> None
drawPolyline(polygon:Union[QPolygon, Sequence[QPoint], QRect]) -> None
drawPolyline(polygon:Union[QPolygonF, Sequence[QPointF], QRectF]) -> None
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QPointF, Qt
from PySide6.QtGui import QPainter, QPaintEvent, QPen
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建画笔对象
pen.setColor("red") # 3.设置钢笔的颜色
pen.setWidth(10) # 4.设置画笔宽度
pen.setJoinStyle(Qt.PenJoinStyle.RoundJoin) # 5.设置画笔连接样式
pen.setCapStyle(Qt.PenCapStyle.RoundCap) # 6.设置画笔端点样式
painter.setPen(pen) # 7.设置绘图对象画笔
p1 = QPointF(10, 10)
p2 = QPointF(self.width() - 10, 10)
p3 = QPointF(10, self.height() - 10)
p4 = QPointF(self.width() - 10, self.height() - 10)
painter.drawPolyline([p1, p2, p3, p4]) # 8.绘制折线
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
5.4、绘制矩形
QPainter 可以一次绘制一个矩形,也可以一次绘制多个矩形。
# 绘制单个矩形
drawRect(rect:QRect) -> None
drawRect(rect:Union[QRect, QRectF]) -> None
drawRect(x:int, y:int, width:int, height:int) -> None
# 绘制多个矩形
drawRects(rectangles:Sequence[QRect]) -> None
drawRects(rectangles:Sequencep[QRectF]) -> None
其中 drawRect(x:int, y:int, width:int, heigth:int) 方法中 x 和 y 参数确定 左上角的位置,width 和 height 参数确定 宽度 和 高度。
圆角矩形是在矩形的基础上对 4 个角分别用一个椭圆进行倒圆角。要绘制圆角矩形,除了需要设置绘制矩形的参数外,还需要设置椭圆的两个半径。

QPainter 绘制椭圆的方法如下:
drawRoundedRect(rect:Union[QRectF,QRect], xRadius:float, yRadius:float, mode:Qt.SizeMode=Qt.AbsoluteSize) -> None
drawRoundedRect(x:int, y:int, w:int, h:int, xRadius:float, yRadius:float, mode:Qt.SizeMode=Qt.AbsoluteSize) -> None
其中参数 mode 是 Qt.SizeMode 类型的枚举值,可以取值如下:
Qt.SizeMode.AbsoluteSize # 椭圆半径是绝对值
Qt.SizeMode.RelativeSize # 椭圆半径是相对于矩形边长的相对值
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import Qt, QRect
from PySide6.QtGui import QPainter, QPaintEvent, QPen
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建画笔对象
pen.setColor("red") # 3.设置钢笔的颜色
pen.setWidth(10) # 4.设置画笔宽度
painter.setPen(pen) # 5.设置绘图对象画笔
# 6.绘制矩形
painter.drawRect(QRect(10, 10, self.width() - 20, self.height() // 2 - 20))
# 7.绘制圆角矩形
painter.drawRoundedRect(QRect(10, self.height() // 2 + 10, self.width() - 20, self.height() // 2 - 20), 50, 30, Qt.SizeMode.AbsoluteSize)
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
5.5、绘制椭圆
一个椭圆有两个半径。确定一个椭圆有两种方法:一种是先确定一个矩形边界,在矩形内部作一个与矩形相切的内切椭圆;另一种是先定义一个中心,再定义两个半径。如果矩形边界是正方形或者椭圆的两个半径相等,椭圆就变成了圆。扇形是椭圆的一部分,绘制扇形时除了确定椭圆的几何数据外,还需要确定扇形的起始角和跨度角。需要特别注意的是,起始角和跨度角都是用输入值的 1/16 计算。

# 绘制椭圆
drawEllipse(center:[QPoint, QPointF], rx:int, ry:int) -> None
drawEllipse(r:QRect) -> None
drawEllipse(r:Union[QRect, QRectF]) -> None
drawEllipse(x:int, y:int, w:int, h:int) -> None
drawEllipse(center:QPainterPath.Element, rx:float, ry:float) -> None
# 绘制扇形
drawPie(rect:Union[QRect, QRectF], a:int, alen:int) -> None
drawPie(x:int, y:int, w:int, h:int, a:int, alen:int) -> None
绘制弧和绘制弦的参数与绘制扇形的参数相同,只不过是从椭圆上截取的部分不同。QPainter 绘制弧和弦的方法如下:
# 绘制弧
drawArc(rect:Union[Qrect, QRectF], a:int, alen:int) -> None
drawArc(x:int, y:int, w:int, h:int, a:int, alen:int) -> None
# 绘制弦
drawChord(rect:Union[QRect, QRectF], a:int, alen:int) -> None
drawChord(x:int, y:int, w:int, h:int, a:int, alen:int) -> None
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import Qt, QRect
from PySide6.QtGui import QPainter, QPaintEvent, QPen
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建画笔对象
pen.setColor("red") # 3.设置钢笔的颜色
pen.setWidth(10) # 4.设置画笔宽度
painter.setPen(pen) # 5.设置绘图对象画笔
# 6.绘制椭圆
painter.drawEllipse(QRect(10, 10, self.width() // 2 - 20, self.height() // 2 - 20))
# 7.绘制扇形
painter.drawPie(QRect(self.width() // 2, self.height() // 2, self.width() // 2 - 20, self.height() // 2 - 20), 45 * 16, 60* 16)
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
5.6、绘制多边形
QPainter 绘制多边形和凸多边形的方法如下所示。
# 绘制多边形
drawPolygon(points:Sequence[QPoint], fill:Qt.FillRule) -> None
drawPolygon(points:Sequence[QPointF], fill:Qt.FillRule) -> None
drawPolygon(polygon:Union[QPolygon, Sequence[QPoint], QRect], fillRule:Qt.FillRule=Qt.OddEvenFill) -> None
drawPolygon(polygon:Union[QPolygonF, Sequence[QPointF], QPolygon, QRectF], fill:Qt.FillRule=Qt.OddEvenFill) -> None
# 绘制凸多边形
drawConvexPolygon(polygon:Union[QPolygon, Sequence[QPoint], QRect]) -> None
drawConvexPolygon(polygon:Union[QPolygonF, Sequence[QPointF], QPolygon, QRectF]) -> None
使用这些方法时,需要给出多边形或凸多边形的顶点,系统会自动在起始点和终止点之间建立直线,使多边形封闭。参数 fill 是 Qt.FillRule 的枚举类型,用于确定一个点是否在图形内部,在内部的区域可以进行填充。fillRule 可以取值如下:
Qt.FillRule.OddEvenFill是 奇偶填充规则,要判断一个点是否在图形中,可以从该点向图形外引一条水平线,如果该水平线与图形的交点个数为奇数,那么该点在图形中。Qt.FillRule.WindingFill是 非零绕组填充规则,要判断一个点是否在图形中,可以从该点向图形外引一条水平线,如果该水平线与图形的边线相交,这个边线是顺时针绘制的,就记为 1,是逆时针绘制的就记为 -1,然后将所有数值相加,若结果不为 0,那么该点就在图形中。

import sys
import math
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import Qt, QPointF
from PySide6.QtGui import QPainter, QPaintEvent, QPen, QBrush
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建画笔对象
pen.setColor("red") # 3.设置钢笔的颜色
pen.setWidth(10) # 4.设置画笔宽度
painter.setPen(pen) # 5.设置绘图对象画笔
# 6、设置画刷
brush = QBrush(Qt.BrushStyle.SolidPattern)
painter.setBrush(brush)
r = 100
x = self.width() / 4
y = self.height() / 4
p1 = QPointF(r * math.cos(-90 * math.pi / 180) + x, r * math.sin(-90 * math.pi / 180) + y)
p2 = QPointF(r * math.cos(-18 * math.pi / 180) + x, r * math.sin(-18 * math.pi / 180) + y)
p3 = QPointF(r * math.cos(54 * math.pi / 180) + x, r * math.sin(54 * math.pi / 180) + y)
p4 = QPointF(r * math.cos(126 * math.pi / 180) + x, r * math.sin(126 * math.pi / 180) + y)
p5 = QPointF(r * math.cos(198 * math.pi / 180) + x, r * math.sin(198 * math.pi / 180) + y)
# 7.绘制多边形
painter.drawPolygon([p1, p3, p5, p2, p4], Qt.FillRule.OddEvenFill)
offset = QPointF(self.width() / 2, 0)
painter.drawPolygon([p1 + offset, p3 + offset, p5 + offset, p2 + offset, p4 + offset], Qt.FillRule.WindingFill)
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
六、绘图路径
为了将简单的图形组合成复杂且封闭的图形,需要用到绘图路径 QPainterPath,前面介绍的绘图方法所绘制的图形都可以加入 QPainterPath 中,构成 QPainterPath 的元素。用 QPainter 的 drawPath(path:QPainterPath) 方法或 strokePath(path:QPainterPath, pen:Union[QPen, Qt.PenStyle, QColor]) 方法可以 将绘图路径的图形绘制出来,用绘图路径绘制的图形不论是否封闭,都隐含是封闭的,可以在其内部进行填充。
QPainterPath 是一些绘图命令按照先后顺序的有序组合,创建一次后可以反复使用。用 QPainterPath 类创建绘图路径实例对象的方法如下所示:
QPainterPath()
QPainterPath(other:QPainterPath)
QPainterPath(startPoint:Union[QPoint, QPointF, QPainterPath.Element])
其中 startPoint 是 绘制路径的起始点,也可以用绘图路径的 moveTo(point:Union[QPointF,QPoint]) 或 moveTo(x:float, y:float) 方法 将绘图路径的当前点移到起始点。
QPainterPath 类与绘图相关的方法:
currentPosition() -> QPointF # 获取当前的起始点QPointF
# 将当前点移动到指定的点,作为下一个绘图单元的起始点
moveTo(p:Union[QPoint, QPointF]) -> None
moveTo(x:float, y:float) -> None
# 将当前点移动到指定矩形框内的椭圆上,angle是起始角度
arcMoveTo(rect:Union[QRect, QRectF], angle:float) -> None
arcMoveTo(x:float, y:float, w:float, h:float, angle:float) -> None
# 在当前点与指定点之间绘制直线
lineTo(p:Union[QPoint, QPointF, QPointerPath.Element]) -> None
lineTo(x:float, y:float) -> None
# 在当前点和终点间绘制三次贝塞尔曲线,前两个点是中间控制点,最后一个点是终点
cubicTo(ctrlPt1:Union[QPoint, QPointF, QPainterPath.Element], ctrlPt2:Union[QPoint, QPointF, QPainterPath.Element], endPty:Union[QPoint, QPointF, QPainterPath.Element]) -> None
cubicTo(ctrlPt1x:float, ctrlPt1y:float, ctrlPt2x:float, ctrlPt2y:float, endPtx:float, endPty:float) -> None
# 在当前点和终点间添加二次贝塞尔曲线,第一个点是控制点
quadTo(ctrlPt:Union[QPoint, QPointF, QPointerPath.Element], endPt:Union[QPoint, QPointF, QPointerPath.Element]) -> None
quadTo(ctrlPtx:float, ctrlPty:float, endPtx:float, endPty:float) -> None
# 在矩形框内绘制圆弧,startAngle和arcLength分别是起始点和跨度角
arcTo(rect:Union[QRect, QRectF], startAngle:float, arcLength:float) -> None
arcTo(x:float, y:float, w:float, h:float, startAngle:float, arcLength:float) -> None
# 绘制封闭的椭圆
addEllipse(rect:Union[QRect, QRectF]) -> None
addEllipse(center:Union[QPoint, QPointF], rx:float, ry:float) -> None
addEllipse(x:float, y:float, w:float, h:float) -> None
# 绘制矩形
addRect(rect:Union[QRect, QRectF]) -> None
addRect(x:float, y:float, w:float, h:float) -> None
# 绘制圆角矩形
addRoundedRect(rect:Union[QRect, QRectF], xRadius:float, yRadius:float, mode:Qt.SizeMode=Qt.AbsoluteSize) -> None
addRoundedRect(x:float, y:float, w:float, h:float, xRadius:float, yRadius:float, mode:Qt.SizeMode=Qt.AbsoluteSize) -> None
# 绘制多边形
addPolygon(polygon:Union[QPolygon, QPolygonF, QPointF, Sequence[QPointF]]) -> None
# 绘制文本
addText(point:Union[QPoint, QPointF, QPainterPath.Element], f:Union[QFont, str, Sequence[str]], text:str) -> None
addText(x:float, y:float, f:Union[QFont, str, Sequence[str]], text:str) -> None
addRegion(region:Union[QRegion, QBitmap, QPolygon, QRect]) -> None # 绘制QRegion的范围
addPath(path:QPainterPath) -> None # 将其它绘图路径添加进来
# 将绘图路径进行平移
translate(offset:Union[QPoint, QPointF, QPainterPath.Element]) -> None
translate(dx:float, dy:float)
closeSubpath() -> None # 有当前子路径的首尾绘制直线,开始新的子路径的绘制
connectPath(path:QPainterPath) -> None # 由当前路径的终点位置与给定路径的起始位置绘制直线
QPainterPath 类与查询相关的方法:
angleAtPercent(t:float) -> float # 获取绘图路径长度百分比处的切向角
slopeAtPercent(t:float) -> float # 获取斜率
boundingRect() -> QRectF # 获取路径所在的边界矩形区域
capacity() -> int # 获取路径中单元的数量
elementCount() -> int # 获取绘图路径的单元数量
clear() -> None # 清空绘图路径中的元素
contains(p:Union[QPoint, QPointF]) -> bool # 如果指定的点在路径内部,则返回True
contains(rect:QRect) -> bool # 如果路径包含指定的矩形,则返回True
contains(pt:QPainterPath.Element) -> bool # 如果包含指定的路径,则返回True
controlPointRect() -> QRectF # 获取包含路径中所有点和控制点构成的矩形
intersected(r:QPainterPath) -> QPainterPath # 获取绘图路径和指定路径填充区域相交的路径
united(r:QPainterPath) -> QPainterPath # 获取绘图路径与指定路径填充区域合并的路径
subtracted(r:QPainterPath) -> QPainterPath # 获取减去指定路径后的路径
intersects(p:QPainterPath) -> bool # 获取绘图路径与指定路径是否相交
intersects(rect:QRectF) -> bool # 获取绘图路径与矩形区域是否相交
isEmpty() -> bool # 获取绘图路径是否为空
length() -> float # 获取绘图路径的长度
pointAtPercent(t:float) -> QPointF # 获取指定长度百分比处的点
reserve(size:int) -> None # 在内存中预留指定数量的绘图单元内存空间
setElementPositionAt(i:int, x:float, y:float) -> None # 将索引是i的元素的x和y坐标设置成指定值
setFillRule(fillRule:Qt.FillRule) -> None # 设置填充规则
simplified() -> QPainterPath # 获取简化后的路径,如果路径元素有交叉或重合,则简化后的路径没有重合
swap(other:QPainterPath) -> None # 交换绘图路径
toReversed() -> QPainterPath # 获取反转后的路径
toSubpathPolygons(matrix:QTransform=QTransform()) -> List[QPolygonF] # 将每个元素转换成QPolygonF
translated(offset:Union[QPoint, QPointF]) -> QPainterPath # 获取平移后的绘图路径
translated(dx:float, dy:float) -> QPainterPath # 获取平移后的绘图路径
路径是由多个图形构成的,每个图形中可能包括直线、贝塞尔曲线、弧、椭圆、多边形、矩形或文本。使用 moveTo() 方法把当前路径移到指定位置,作为绘图开始的起点位置,移动当前点会启用一个新的子路径,并自动封闭之前的路径。
用 lineTo() 方法 绘制直线,用 arcTo() 方法 绘制弧,用 quadTo() 方法和 cubicTo() 方法 绘制二次和三次贝塞尔曲线,用 addEllipse() 方法 绘制封闭的椭圆,用 addPolygon() 方法 绘制多边形,用 addRect() 方法和 addRoundedRect() 方法 绘制矩形。在添加直线、弧或贝塞尔曲线后,当前点移动到这些元素的最后位置。绘制弧时,弧的零度角与钟表的 3 时方向相同,逆时针方向为正。
路径中每个绘图步骤称为 单元,比如 moveTo()、lineTo()、arcTo() 都是 单元,addRect()、addPolygon() 等都是用 moveTo()、lineTo()、arcTo() 等绘制的。例如 addRect(100, 50, 200, 200) 由 movetTo(100, 50)、lineTo(300, 50)、lineTo(300, 250)、lineTo(100, 250) 和 lineTo(100, 50) 共 5 个单元构成。
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QPointF, Qt
from PySide6.QtGui import QPainter, QPaintEvent, QPen
from PySide6.QtGui import QPainterPath
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
center = QPointF(self.width() / 2, self.height() / 2)
r = min(self.width() , self.height()) / 3
painter = QPainter(self) # 1.创建绘图对象
pen = QPen() # 2.创建画笔
pen.setWidth(10) # 3.设置画笔宽度
pen.setColor(Qt.GlobalColor.black) # 4.设置画笔颜色
painter.setPen(pen) # 5.使用钢笔对象
path = QPainterPath() # 6.创建路径
path.moveTo(center) # 7.将当前点移动到指定点,作为起始点
path.arcTo(center.x() - r, center.y() - r, 2 * r, 2 * r, 0, 360) # 8.绘制圆弧
path.setFillRule(Qt.FillRule.WindingFill) # 9.设置填充方式
painter.drawPath(path) # 10.绘制路径
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
七、绘制文本
可以在指定位置绘制文本,绘制文本时,通常需要先用 setFont(font:QFont) 方法 设置 QPainter 的字体。绘制文本的方法如下所示,所绘文本默认是反锯齿的。
drawStaticText(left:int, top:int, staticText:QStaticText) -> None
drawStaticText(topLeftPosition:Union[QPoint, QPointF, QPainterPath.Element], staticText:QStaticText) -> None
drawText(p:QPoint, s:str) -> None
drawText(p:Union[QPoint, QPointF, QPainterPath.Element], s:str) -> None
drawText(x:int, y:int, s:str) -> None
drawText(r:Union[QRect, QRectF], flags:int, text:str) -> None
drawText(x:int, y:int, w:int, h:int, flags:int, text:str) -> None
绘制文本可以用 drawStaticText() 方法,该方法比较快,且每次不用重新计算文本的排列位置。QStaticText 是 静态文本类,用 QStaticText 类创建静态文本的方法是 QStaticText() 或 QStaticText(text:str)。可以用 QStatciText 的 setText(text:str) 方法 设置文本。
可以用 setTextFormat(format:Qt.TextFormat) 方法 设置静态文本的格式,参数 format 是 Qt.TextFormat 类型的枚举值,可以取值如下:
Qt.TextFormat.PlainText
Qt.TextFormat.RichText
Qt.TextFormat.AutoText
Qt.TextFormat.MarkdownText
如果所绘制的文本用当前的字体绘制时,给定的矩形范围不合适,可以用 boundingRect() 方法 获取边界矩形。
boundingRect(rect:QRect, flags:int, text:str) -> QRect
boundingRect(rect:Union[QRectF, QRect], flags:int, text:str) -> QRectF
boundingRect(rect:Union[QRectF, QRect], text:str, alignmeng:Qt.Alignment) -> QRect
boundingRect(x:int, y:int, width:int, height:int, flags:int, text:str) -> QRect
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPaintEvent, QPen
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
font = painter.font() # 2.获取字体对象
font.setFamily("楷体") # 3.设置字体名称
font.setPointSize(50) # 4.设置字体大小
font.setBold(True) # 5.设置字体是否加粗
font.setItalic(True) # 6.设置字体是否斜体
painter.setFont(font) # 7.使用字体对象
pen = QPen() # 8.创建画笔对象
pen.setColor("red") # 9.设置钢笔的颜色
pen.setWidth(10) # 10.设置画笔宽度
painter.setPen(pen) # 11.设置绘图对象画笔
painter.drawText(10, 100, "你好,世界!") # 12.绘制文本
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
八、填充图形
用 QPainter 绘图时,如果所绘制的图形是封闭的,且为 QPainter 设置了画刷,则系统自动在封闭的图形内填充画刷的图案,封闭的图形包括绘图路径、矩形、椭圆、多边形。除此之外,还可以为指定的矩形范围填充图案,此时不需要有封闭的边界线。
QPainter 类的用来填充的常用方法如下:
# 为指定的路径填充颜色
fillPath(path:QPainterPath, brush:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradient, QImage, QPixmap]) -> None
# 用画刷填充指定的矩形区域
fillRect(path:Union[QRect, QRectF], brush:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, str, QGradient, QImage, QPixmap]) -> None
# 用颜色和渐变色填充指定的矩形区域
fillRect(x:int, y:int, width:int, height:int, color:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, str, QGradient, QImage, QPixmap]) -> None
# 擦除指定区域的填充
eraseRect(rect:Union[QRect, QRectF]) -> None
eraseRect(x:int, y:int, width:int, height:int) -> None
setBackground(bg:Union[QBrush, QColor, Qt.GlobalColor, QGradient]) -> None # 设置背景色
background() -> QBrush # 获取背景画刷
setBackgroundMode(mode:Qt.BGMode) -> None # 设置背景模式
setBrushOrigin(x:int, y:int) -> None # 设置画刷的起始点
setBrushOrigin(point:Union[QPoint, QPointF, QPainterPath.Element]) -> None # 设置画刷的起始点
brushOrigin() -> QPoint # 获取起始点QPoint
用 fillRect() 方法可以 给指定的矩形区域绘制填充颜色,这时无须封闭的空间,也不会绘制出轮廓。用 eraseRect() 方法可以 擦除矩形区域的填充。
用 setBackgroundMode(mode:Qt.BGMode) 方法 设置背景的模式,其中参数 mode 是 Qt.BGMode 类型的枚举值,可以取值如下:
Qt.BGMode.TransparentMode # 透明模式
Qt.BGMode.OpaqueMode # 不透明模式
用 setBackground(color:Union[QBrush, QColor, Qt.GlobalColor, QGradient]) 方法 设置背景色,背景色只有在不透明模式下才起作用。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPaintEvent
from PySide6.QtGui import QLinearGradient, QPen, QBrush
from PySide6.QtCore import QPointF, Qt
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
font = painter.font() # 2.获取字体对象
font.setFamily("楷体") # 3.设置字体名称
font.setPointSize(50) # 4.设置字体大小
font.setBold(True) # 5.设置字体是否加粗
painter.setFont(font) # 6.使用字体对象
linear1 = QLinearGradient(QPointF(0, 0), QPointF(self.width(), self.height())) # 7.使用线性渐变充当文字颜色
# 8.设置文件线性渐变的颜色
linear1.setStops([(0, Qt.GlobalColor.red), (0.3, Qt.GlobalColor.yellow), (0.6, Qt.GlobalColor.green), (1, Qt.GlobalColor.blue)])
linear1.setSpread(QLinearGradient.Spread.ReflectSpread) # 9.设置扩展模式
brush1 = QBrush(linear1) # 10.用线性渐变定义画刷
pen = QPen() # 11.定义画笔
pen.setBrush(brush1) # 12.将画刷设置给画笔
painter.setPen(pen) # 13.设置绘图对象画笔
painter.setBackgroundMode(Qt.BGMode.OpaqueMode) # 14.设置背景模式不透明
linear2 = QLinearGradient(QPointF(0, 0), QPointF(self.width(), self.height())) # 15.使用线性渐变充当文字背景颜色
# 16.设置颜色
linear2.setStops([(0, Qt.GlobalColor.blue), (0.3, Qt.GlobalColor.green), (0.6, Qt.GlobalColor.red), (1, Qt.GlobalColor.white)])
linear2.setSpread(QLinearGradient.Spread.ReflectSpread) # 17.设置扩展模式
brush2 = QBrush(linear2) # 18.用线性渐变定义画刷
painter.setBackground(brush2) # 19.设置背景画刷
painter.setBrushOrigin(0, 0) # 20.设置画刷的起始点
painter.drawText(100, 100, "你好,世界!") # 21.绘制字体
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
九、绘制图像
QPainter 还可以把 QPixmap、QImage 和 QPicture 将 图像直接绘制在绘图设备上。
【1】、QPixmap 图像
绘制 QPixmap 图像的方法如下所示,可以将图像按照原始尺寸显示,也可以缩放图像到一个矩形区域中显示,还可以从原图像上截取一部分绘制到一个矩形区域。
# 指定绘图设备上的一个点作为左上角,按照图像原始尺寸显示
drawPixmap(p:Union[QPoint, QPointF, QPainterPath.Element], pm:Union[QPixmap, QImage, str]) -> None
drawPixmap(x:int, y:int, pm:Union[QPixmap, QImage, str]) -> None
# 指定绘图设备上的矩形区域,以缩放尺寸方式显示
drawPixmap(r:QRect, pm:Union[QPixmap, QImage, str]) -> None
drawPixmap(x:int, y:int, w:int, h:int, pm:Union[QPixmap, QImage, str]) -> None
# 指定绘图设备上的一个点和图像的矩形区域,裁剪显示图像
drawPixmap(p:Union[QPoint, QPointF, QPainterPath.Element], pm:Union[QPixmap, QImage, str], sr:Union[QRect, QRectF]) -> None
drawPixmap(x:int, y:int, pm:Union[QPixmap, QImage, str], sx:int, sy:int, sw:int, sh:int) -> None
# 指定绘图设备上的矩形区域和图像的矩形区域,裁剪并缩放显示图像
drawPixmap(targetRect:Union[QRect, QRectF], pixmap:Union[QPixmap, QImage, str], sourceRect:Union[QRect, QRectF]) -> None
drawPixmap(x:int, y:int, w:int, h:int, pm:Union[QPixmap, QImage, str], sx:int, sy:int, sw:int, sh:int) -> None
# 以平铺方式绘制图片
drawTiledPixmap(x:int, y:int, w:int, h:int, pm:Union[QPixmap, QImage, str], sx:int=0, sy:int=0) -> None
drawTiledPixmap(rect:QRect, pm:Union[QPixmap, QImage, str], pos:QPoint=QPoint()) -> None
drawTiledPixmap(rect:Union[QRect, QRectF], pm:Union[QPixmap, QImage, str], offset:Union[QPoint, QPointF, QPainterPath.Element]=QPointF()) -> None
# 绘制图像的多个部分,可以对每个部分进行缩放、旋转操作
drawPixmapFragments(fragments:list[QPainter.PixmapFragment], fragmentCount:int, pixmap:Union[QPixmap, QImage, str], hints:QPainter.PixmapFragmentHints=QPainter.PixmapFragmentHints()) -> None
用 drawPixmapFragments(fragments:list[QPainter.PixmapFragment], fragmentCount:int, pixmap:Union[QPixmap, QImage, str], hints:QPainter.PixmapFragmentHints) 方法可以 截取图像的多个区域,并对每个区域进行缩放、旋转操作,其中参数 hints 只能取 QPainter.PixmapFragmentHints.OpaqueHint。参数 QPainter.PixmapFragment 的创建方法如下:
QPainter.PixmapFragment.create(pos:QPointF,sourceRect:QRectF, scaleX:int=1, scaleY:int=1, rotation:int=0, opacity:int=1)
其中 pos 是 图像绘制地点,sourceRect 是 截取的图像的部分区域,scaleX 和 scaleY 是 缩放比例,rotation 是 旋转角度,opacity 是 不透明度值。
【2】、QImage 图像
绘制 QImage 图像的方法如下所示。可以将图像按照原始尺寸显示,也可以缩放图像到一个矩形区域中显示,还可以从原图像上截取一部分绘制到一个矩形区域。
# 在指定位置,按图像实际尺寸显示
drawImage(p:Union[QPoint, QPointF, QPainterPath.ELement], image:Union[QImage, str]) -> None
# 在指定矩形区域内,图像进行缩放显示
drawImage(r:Union[QRect, QRectF], image:Union[QImage, str]) -> None
# 在指定位置,从图像上截取一部分显示
drawImage(p:Union[QPoint, QPointF, QPainterPath.Element], image:Union[QImage, str], sr:Union[QRect, QRectF], flags:Qt.ImageConversionFlags=Qt.AutoColor) -> None
drawImage(x:int, y:int, image:Union[QImage, str], sx:int=0, sy:int=0, sw:int=-1, sh:int=-1, flags:Qt.ImageConversionFlags=Qt.AutoColor) -> None
# 从图像上截取一部分,以缩放形式显示在指定的矩形区域内
drawImage(targetRect:Union[QRect, QRectF], image:Union[QImage, str], sourceRect:Union[QRect, QRectF], flags:Qt.ImageConversionFlags=Qt.AutoColor) -> None
其中 flags 参数是 Qt.ImageConversionFlags 枚举值,可取值如下:
Qt.ImageConversionFlags.AutoColor
Qt.ImageConversionFlags.ColorOnly
Qt.ImageConversionFlags.MonoOnly
【3】、QPicture 图像
对于 QPicture 图像,只能在绘图设备的指定点上按照原始尺寸进行绘制。绘制 QPicture 图像的方法如下:
drawPicture(x:int, y:int, picture:Union[QPicture,int]) -> None
drawPicture(p:Union[QPointF, QPoint, QPainterPath.Element], picture:Union[QPicture,int]) -> None
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPaintEvent, QImage
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
image = QImage("assets/images/1.jpg") # 2.创建图像对象
painter.drawImage(self.rect(), image) # 3.绘制图像
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
十、裁剪区域
当所绘图形比较大时,若只想显示绘图上的一部分区域的内容,其他区域的内容不显示,就需要使用裁剪区域。用 QPainter 设置裁剪区域的方法下所示:
setClipping(enable:bool) -> None # 设置是否启动裁剪区域
hasClipping() -> bool # 获取是否有裁剪区域
setClipPath(path:QPainterPath, op:Qt.ClipOperation=Qt.ReplaceClip) -> None # 用路径设置裁剪区域
clipPath() -> QPainterPath # 获取裁剪区域的路径
setClipRect(rect:Union[QRect, QRectF], op:Qt.ClipOperation=Qt.ReplaceClip) -> None # 用矩形框设置裁剪区域
setClipRect(x:int, y:int, w:int, h:int, op:Qt.ClipOperation=Qt.ReplaceClip) -> None # 用矩形框设置裁剪区域
# 用QRegion设置裁剪区域
setClipRegion(arg_1:Union[QRegion, QBitmap, QPolygon, QRect], op:Qt.ClipOperation=Qt.ReplaceClip) -> None
clipRegion() -> QRegion # 获取裁剪区域
clipBoundingRect() -> QRectF # 获取裁剪区域的边界矩形
其中参数 op 是 Qt.ClipOperation 类型的枚举值,可以取值如下:
Qt.ClipOperation.NoClip
Qt.ClipOperation.ReplaceClip # 替换裁剪区域
Qt.ClipOperation.IntersectClip # 与现有裁剪区域取交集
QRegion 类专门用于 定义裁剪区域,QWidget 的 repaint() 方法可以接受 QRegion 参数,限制刷新的范围。用 QRegion 类创建裁剪区域实例的方法如下:
QRegion()
QRegion(bitmap:Union[QBitmap, str])
QRegion(pa:Union[QPolygon, Sequence[QPoint], QRect], fillRule:Qt.FillRule=Qt.OddEvenFill)
QRegion(r:QRect, t:QRegion.RegionType=QRegion.Rectangle)
QRegion(region:Union[QRegion, QBitmap, QPloygon, QRect])
QRegion(x:int, y:int, w:int, h:int, t:QRegion.RegionType=QRegion.Rectangle)
其中 t 是 QRegion.RegionType 类型的枚举值,可以取值如下:
QRegion.RegionType.Rectangle
QRegion.RegionType.Ellipse
QRegion 类的常用方法如下:
boundingRect() -> QRect # 获取边界
contains(p:QPoint) -> bool # 获取是否包含指定的点
contains(r:QRect) -> bool # 获取是否包含矩形
isEmpty() -> bool # 获取是否为空
isNull() -> bool # 获取是否无效
setRects(rect:QRect, num:int) -> None # 设置多个矩形区域
rectCount() -> int # 获取矩形区域的数量
begin() -> QRect # 获取第一个非重合的矩形
cbegin() -> QRect # 获取第一个非重合的矩形
end() -> QRect # 获取最后一个非重合的矩形
cend() -> QRect # 获取最后一个非重合的矩形
intersects(r:Union[QRegion, QBitmap, QPolygon, QRect]) -> bool # 获取是否与区域相交
intersected(r:Union[QRegion, QBitmap, QPolygon, QRect]) -> QRegion # 获取相交的区域
subtracted(r:Union[QRegion, QBitmap, QPolygon, QRect]) -> QRegion # 获取减去区域后的区域
united(r:Union[QRegion, QBitmap, QPolygon, QRect]) -> QRegion # 获取合并后的区域
xored(r:Union[QRegion, QBitmap, QPolygon, QRect]) -> QRegion # 获取异或区域
translate(p:QPoint) -> None # 平移区域
translate(dx:int, dy:int) -> None # 平移区域
translated(p:QPoint) -> QRegion # 获取平移后的区域
translated(dx:int, dy:int) -> QRegion # 获取平移后的区域
swap(other:Union[QRegion, QBitmap, QPolygon, QRect]) -> None # 交换区域
QRegion 可以进行交、减、并和异或运算,这些运算的示意图如下所示。

用 setRects(rect:Sequence[QRect]) 方法可以 设置多个矩形区域,多个矩形之间不能相互交叉,处于同一层的矩形必须有相同的高度,而不能连在一起,多个矩形可以合并成一个矩形。多个矩形首先按 y 值以升序排列,其次按 x 值以升序排列。
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPaintEvent, QPixmap, QRegion
from PySide6.QtCore import QRect
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
pixmap = QPixmap("assets/images/1.jpg") # 2.创建图像对象
painter.setClipping(True) # 3.设置是否启动裁剪区域
# 4.裁剪区域
rect1 = QRect(self.width() // 20, self.height() // 10, self.width() // 10 * 4, self.height() // 10 * 3)
rect2 = QRect(self.width() // 20, self.height() // 10 * 5, self.width() // 10 * 4, self.height() // 10 * 3)
rect3 = QRect(self.width() // 20 * 11, self.height() // 10, self.width() // 10 * 4, self.height() // 10 * 3)
rect4 = QRect(self.width() // 20 * 11, self.height() // 10 * 5, self.width() // 10 * 4, self.height() // 10 * 3)
region1 = QRegion(rect1) # 4.矩形裁剪区域
region2 = QRegion(rect2)
region3 = QRegion(rect3, t=QRegion.RegionType.Ellipse) # 5.椭圆裁剪区域
region4 = QRegion(rect4, t=QRegion.RegionType.Ellipse)
region = region1.united(region2).united(region3).united(region4) # 6.裁剪区域的布尔运算,并集运算
painter.setClipRegion(region) # 7.用QRegion设置裁剪区域
painter.drawPixmap(self.rect(), pixmap) # 8.绘制图像
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
十一、图形合成
图形合成 是指当绘制新图形时,绘图设备上已经存在旧图形,对新图形和旧图形进行处理的方法。图形合成是基于像素,将旧图形的颜色值和 Alpha 通道的值与新图形的颜色值和 Alpha 通道的值进行合成处理。图形合成的处理 使用 QPainter 的 setCompositionMode(mode:QPainter.CompositionMode) 方法设置,用 compositionMode() 方法 获取合成模式,其中参数 mode 是 QPainter.CompositionMode 的类型枚举值,可以取值如下:
QPainter.CompositionMode.CompositionMode_Source
QPainter.CompositionMode.CompositionMode_SourceIn
QPainter.CompositionMode.CompositionMode_SourceOut
QPainter.CompositionMode.CompositionMode_SourceAtop
QPainter.CompositionMode.CompositionMode_SourceOver # 默认值
QPainter.CompositionMode.CompositionMode_Destination
QPainter.CompositionMode.CompositionMode_DestinationIn
QPainter.CompositionMode.CompositionMode_DestinationOut
QPainter.CompositionMode.CompositionMode_DestinationAtop
QPainter.CompositionMode.CompositionMode_DestinationOver
QPainter.CompositionMode.CompositionMode_Clear
QPainter.CompositionMode.CompositionMode_Xor
修改 template.py 文件的内容。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPaintEvent, QPixmap
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.resize(800, 600) # 2.设置窗口对象大小
def paintEvent(self, event:QPaintEvent):
painter = QPainter(self) # 1.创建绘图对象
pixmap = QPixmap("assets/images/1.jpg") # 2.创建图像对象
painter.drawPixmap(self.rect(), pixmap) # 3.绘制图像
painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceAtop) # 4.设置图像的合成方式
ico = QPixmap("assets/images/1.png")
painter.drawPixmap(10, 10, ico) # 5.绘制图标
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束

浙公网安备 33010602011771号