31. 绘图技术

news/2025/1/19 17:30:04/文章来源:https://www.cnblogs.com/FlurryHeart/p/18679736

一、QPainter绘图

  绘图是指在绘图设备(窗口、控件、图像、打印机等)上将用户构思出的图形绘制出来,图形包括点、线、矩形、多边形、椭圆、文字及保存到磁盘上的图像等。可以对绘制的图形进行处理,如给封闭的图形填充颜色。

  绘图设备是从 QPaintDevice 继承的类,包括继承自 QWidget 的窗口、各种控件、QPixmap 和 QImage。如果绘图设备是窗口或控件,则 QPainter 绘图一般放到 paintEvent() 事件或者被 paintEvent() 事件调用的函数中。

  我们可以在终端中使用 pip 安装 pyside6 模块。

pip install pyside6

  用 QPainter 类创建绘图实例的方法如下:

QPainter()
QPainter(device=QPaintDevice)

  其中 QPaintDevice 是指继承自 QPaintDevice 的绘图设备。如果使用不带设备的 QPainter() 方法创建实例对象,,则在开始绘图前需要用 painter.begin(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,n Qt.GlobalColor, QColor, QGradient, QImage, QPixmap]) -> None   # 设置画刷
setBrush(style:Qt.BrushStyle) -> None                                                                       # 设置画刷
setBrushOrigin(arg__1: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()
QPen(s:Qt.PenStyle)
QPen(brush:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradient, QImage, QPixmap], width:float, s:Qt.PenStyle=Qt.SolidLine, c:Qt.PenCapstyle=Qt.SquareCap, j:Qt.PenJoinstyle=Qt.BevelJoin)
QPen(color:Union[QColor, Qt.GlobalColor, str, int])
QPen(pen:Union[QPen, Qt.PenStyle, QColor])

  其中 s 是 Qt.PenStyle 的枚举值,用于设置钢笔的样式;画刷 brush 可以用 QBrush、QColor、Qt.GlobalColor 和 QGradient 来设置;c 是 Qt.PenCapStyle 的枚举值,用于设置线条端点样式;j 是 Qt.PenJoinStyle 的枚举值,用于设置线条连接点处的样式。钢笔默认的颜色是黑色,宽度是 1 像素,样式是实线,端点样式是 Qt.SquareCap,连接处是 Qt.BevelJoin。

  QPen 类的常用方法如下:

setStyle(arg__1: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(pcs: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(pcs:Qt.PenJoinStyle) -> None                                                                   # 设置两相交线连接点出的样式
setMiterLimit(limit:float) -> None                                                                          # 设置斜接延长线的长度

  线条的宽度用 setWidth(int)setWidthF(float) 方法设置,如果宽度始终为 0,表示是装饰线条;装饰线条也可用 setCosmetic(bool) 方法设置。装饰线条是指具有恒定宽度的边,可确保线条在不同缩放比例下具有相同的宽度。

  线条的样式用 setStyle(Qt.PenStyle) 方法设置,参数 Qt.PenStyle 可取的值如下所示。

Qt.PenStyle.NoPen               # 不绘制线条
Qt.PenStyle.SolidLine           # 实线
Qt.PenStyle.DashLine            # 虚线
Qt.PenStyle.DotLine             # 点线
Qt.PenStyle.DashDotLine         # 点画线
Qt.PenStyle.DashDotDotLine      # 双点划线
Qt.PenStyle.CustomDashLine      # 自定义线

钢笔的样式

  钢笔的端点样式用 setCapStyle(Qt.PenCapStyle) 方法设置,其中参数 Qt.PenCapStyle 可取值如下:

Qt.PenCapStyle.FlatCap          # 不包含端点
Qt.PenCapStyle.SquareCap        # 包含端点
Qt.PenCapStyle.RoundCap         # 包含端点,并延长半个宽度

钢笔的端点

  两个线条连接点处的样式用 setJoinStyle(Qt.PenJoinStyle) 方法设置,其中参数 Qt.PenJoinStyle 可取值如下:

Qt.PenJoinStyle.MiterJoin
Qt.PenJoinStyle.BevelJoin
Qt.PenJoinStyle.RoundJoin
Qt.PenJoinStyle.SvgMiterJoin

线条连接样式

  线条连接样式是 Qt.MiterJoin 时,用 setMiterLimit(float) 方法设置延长线的长度,其中参数 float 是线条宽度的倍数,默认是2.0,其延长线的含义如下所示。

延长线

  用 setDashPattern(Sequence[float]) 方法可以自定义虚线样式,其中参数的奇数项表示实线的长度,偶数项表示空白处的长度,长度以线宽为单位,表示为线宽的倍数。

  用 setDashOffset(float) 方法可以设置虚线开始绘制的点与线起始点之间的距离,如果这个距离是动态的,则会形成动画效果。

import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPen
from PySide6.QtCore import Qt, QPointFclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2、创建画笔对象pen = QPen()# 3、设置线条颜色pen.setColor(Qt.GlobalColor.blue)# 4、设置线条的宽度pen.setWidth(10)# 5、设置线条样式pen.setStyle(Qt.PenStyle.DashDotDotLine)# 6、设置线条的端点样式pen.setCapStyle(Qt.PenCapStyle.RoundCap)# 7、设置两个线条连接点处的样式pen.setJoinStyle(Qt.PenJoinStyle.RoundJoin)# 8、设置画笔painter.setPen(pen)# 0、绘制一条折线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])if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

三、设置画刷

  对于封闭的图形,如矩形、圆等,用画刷 QBrush 可以在其内部填充颜色、样式、渐变、纹理或图案。

  用 QBrush 类创建画刷的方法如下所示。

QBrush()
QBrush(brush:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradient, QImage, QPixmap])
QBrush(bs:Qt.BrushStyle)
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(arg__1: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(arg__1:QTransform) -> None                     # 设置变换矩阵
transform() -> QTransform                                   # 获取变换矩阵
isOpaque() -> bool                                          # 设置是否不透明

  画刷的风格用 setStyle(Qt.BrushStyle) 方法设置,其中参数 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(QPixmap)setTextureImage(QImage) 方法来设置,这时样式被设置成 Qt.TexturePattern。

import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QBrush
from PySide6.QtCore import Qt, QPointF, QRectFclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2、创建画刷对象brush = QBrush()# 3、设置画刷颜色brush.setColor(Qt.GlobalColor.blue)# 4、设置画刷样式brush.setStyle(Qt.BrushStyle.CrossPattern)# 5、设置画刷painter.setBrush(brush)# 6、绘制一个矩形p1 = QPointF(self.width() / 4, self.height() / 4)p2 = QPointF(3 * self.width() / 4, 3 * self.height() / 4)painter.drawRect(QRectF(p1, p2))if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

四、渐变色

  在用画刷进行填充时,可以设置填充颜色为渐变色。所谓渐变色是指在两个不重合的点处分别设置不同的颜色,这两个点一个是起点,另一个是终点,这两个点之间的颜色从起点的颜色逐渐过渡到终点的颜色。

  定义渐变色的类是 QGradient,渐变样式分为 3 种类型,分别为 线性渐变 QLinearGradient、径向渐变 QRadialGradient 和 圆锥渐变 QConicalGradient,它们都继承自 QGradient 类,也会继承 QGradient 类的属性和方法。

渐变样式

  用 QLinearGradient 类创建线性渐变色的方法如下所示。线性渐变需要一个线性渐变矩形区域(起始和终止位置),参数用于确定这个矩形区域。

QLinearGradient()
QLinearGradient(start:Union[QPointF, QPoint, QPainterPath.Element], finalStop:Union[QPointF, QPainterPath.Element])
QLinearGradient(xStart:float, yStart:float, xFinalStop:float, yFinalStop:float)

  用 QRadialGradient 类创建径向渐变色的方法如下。径向渐变需要的几何参数下所示,需要确定圆心位置、半径、焦点位置和焦点半径。径向渐变的构造函数中,第 1 个参数是圆心位置,可以用点或坐标定义;第 2 个参数是半径;第 3 个参数是焦点位置,可以用点或坐标定义;第 4 个参数是焦点半径。如果焦点设置到圆的外面,则取圆上的点作为焦点。

QRadialGradient()
QRadialGradient(center:Union[QPointF, QPoint, QPainterPath.Element], centerRadius:float, focalPoint:Union[QPointF, QPoint, QPainterPath.Element], focalRadius:float)
QRadialGradient(center:Union[QPointF, QPoint, QPainterPath.Element], radius: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(cx:float, cy:float, radius:float)
QRadialGradient(cx:float, cy:float, radius:float, fx:float, fy:float)

  用 QConicalGradient 创建圆锥渐变色的方法如下所示。圆锥渐变需要的几何参数为圆心位置和起始角度 a,角度必须在 0°~360° 之间,圆心位置可以用点或坐标来定义。

QConicalGradient()
QConicalGradient(center:Union[QPointF, QPoint, QPainterPath.Element], startAngle:float)
QConicalGradient(cx:float, cy:float, startAngle:float)

径向渐变和圆锥渐变的几何参数

  QLinearGradient、QRadialGradient 和 QConicalGradient 继承自 QGradient,因此也会继承 QGradient 的方法。QGradient 类的常用方法如下:

setCoordinateMode(mode:QGradient.CoordinateMode) -> None                    # 设置坐标模式
setColorAt(pos:float, color:Union[QColor, Qt.GlobalColor, str]) -> None     # 设置颜色
setStops(stops:Sequence[Tuple[float, QColor]]) -> None                      # 设置颜色
setInterpolationMode(mode:QGradient.InterpolationMode) -> None              # 设置插值模式
setSpread(spread:QGradient.Spread) -> None                                  # 设置扩展模式
type() -> QGradient.Type                                                    # 获取类型

  在渐变区域内,可以在多个点设置颜色值,这些点之间的颜色值根据两侧的颜色来确定。在定义内部点的颜色值时,通常通过逻辑坐标来定义,渐变区域内的起始点的逻辑值是 0,终止点的逻辑值是 1。如果要在中间位置定义颜色,可以用 setColorAt() 方法来定义。我们也可以用 setStops() 方法一次定义多个颜色值。

  用 setCoordinateMode(QGradient.CoordinateMode) 方法可以设置坐标的模式,参数 QGradient.CoordinateMode 的取值如下所示。

QGradient.CoordinateMode.LogicalMode            # 逻辑方式,起始点为0,终止点为1,这是默认值
QGradient.CoordinateMode.ObjectMode             # 相对于绘图区域矩形边界的逻辑坐标,左上角的坐标是(0, 0),右下角的坐标是(1, 1)
QGradient.CoordinateMode.StretchToDeviceMode    # 相对于绘图设备矩形边界的逻辑坐标,左上角的坐标是(0, 0),右下角的坐标是(1, 1)
QGradient.CoordinateMode.ObjectBoundingMode     # 与ObjectMode基本相同,除了QBrush.transform()应用与逻辑空间而不是物理空间

  当设置的渐变区域小于填充区域时,渐变颜色可以扩展到渐变区域以外的空间。扩展模式用 setSpread(QGradient.Spread) 方法定义,参数 QGradient.Spread 的取值如下所示。扩展模式不适合圆锥渐变,圆锥渐变没有固定的边界。

QGradient.Spread.PadSpread          # 用最近的颜色扩展
QGradient.Spread.RepeatSpread       # 重复渐变
QGradient.Spread.ReflectSpread      # 对称渐变

  用 setInterpolationMode(mode:QGradient.InterpolationMode) 方法设置渐变色内部的插值模式,参数可取值如下:

QGradient.InterpolationMode.ColorInterpolation
QGradient.InterpolationMode.ComponentInterpolation

  用 type() 方法可以获取渐变类型,返回值可能如下:

QGradient.Type.LinearGradient
QGradient.Type.RadialGradient
QGradient.Type.ConicalGradient
QGradient.Type.NoGradient        # 无渐变色

  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                                                  # 获取终止点

  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                                            # 设置焦点半径

  QConicalGradient 类的常用方法:

setCenter(center:Union[QPointF, QPoint]) -> None            # 设置圆心
setCenter(x:float, y:float) -> None                         # 设置圆心
setAngle(angle:float) -> None                               # 设置起始角度
import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPen, QBrush
from PySide6.QtGui import QLinearGradient, QRadialGradient, QConicalGradient
from PySide6.QtCore import Qt, QPointF, QRectFclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):w = self.width()h = self.height()# 1、创建绘图对象painter = QPainter(self)# 2.1、创建钢笔对象,绘制边框pen = QPen()# 2.2、设置边框宽度pen.setWidth(5)# 2.3、设置边框颜色pen.setColor(Qt.GlobalColor.darkBlue)# 2.4、设置边框样式pen.setStyle(Qt.PenStyle.DashLine)# 2.5、设置钢笔painter.setPen(pen)# 3.1、线性渐变linear = QLinearGradient(QPointF(0, 0), QPointF(w / 8, 0))# 3.2、设置颜色linear.setStops([(0, Qt.GlobalColor.red), (0.3, Qt.GlobalColor.yellow), (0.6, Qt.GlobalColor.green), (1, Qt.GlobalColor.blue)])# 3.3、设置扩展模式linear.setSpread(QLinearGradient.Spread.ReflectSpread)# 3.4、用线性渐变定义画刷brush = QBrush(linear)# 3,5、设置画刷painter.setBrush(brush)# 3.6、绘制矩形painter.drawRect(QRectF(0, 0, w / 2, h / 2))# 4.1、镜像渐变radial = QRadialGradient(QPointF(w / 4 * 3, h / 4), w / 8, QPointF(w / 4 * 3, h / 4), w / 15)# 4.2、设置颜色radial.setColorAt(0, Qt.GlobalColor.red)radial.setColorAt(0.5, Qt.GlobalColor.yellow)radial.setColorAt(1, Qt.GlobalColor.blue)# 4.3、设置扩展模式radial.setSpread(QRadialGradient.Spread.RepeatSpread)# 4.4、用镜像渐变创建画刷brush = QBrush(radial)# 4.5、设置画刷painter.setBrush(brush)# 4.6、绘制矩形painter.drawRect(QRectF(w / 2, 0, w / 2, h / 2))# 5.1、圆锥渐变conical = QConicalGradient(QPointF(w / 4, h / 4 * 3), h / 6)# 5.2、设置开始角度conical.setAngle(60)# 5.3、设置颜色conical.setColorAt(0, Qt.GlobalColor.red)conical.setColorAt(1, Qt.GlobalColor.yellow)# 5.4、以圆锥渐变创建画刷brush = QBrush(conical)# 5.5、设置画刷painter.setBrush(brush)# 5.6、绘制矩形painter.drawRect(QRectF(0, h / 2, w / 2, h / 2))# 6.1、镜像渐变radial = QRadialGradient(QPointF(w / 4 * 3, h / 4 * 3), w / 6, QPointF(w / 5 * 4, h / 5 * 4), w / 10)# 6.2、设置颜色radial.setColorAt(0, Qt.GlobalColor.red)radial.setColorAt(0.5, Qt.GlobalColor.yellow)radial.setColorAt(1, Qt.GlobalColor.blue)# 6.3、设置扩展模式radial.setSpread(QRadialGradient.Spread.ReflectSpread)# 6.4、用镜像渐变创建画刷brush = QBrush(radial)# 6.5、设置画刷painter.setBrush(brush)# 6.6、绘制矩形painter.drawRect(QRectF(w / 2, h / 2, w / 2, h / 2))if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

五、绘制几何图形

  QPainter 可以在绘图设备上绘制点、直线、折线、矩形、椭圆、弧、弦、文本和图像等。

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(arg__1:Sequence[QPointF]) -> None
drawPoints(arg__1:Sequence[QPoint]) -> None
drawPoints(points:Union[QPolygon, Sequence[QPoint], QRect])
drawPoints(points:Union[QPolygon, Sequence[QPoint], QPolygon, QRectF])

  创建 QPolygon 实例的方法如下:

QPolygon()
QPolygon(arg_1:Sequence[QPoint])

  创建 QPolygonF 实例的方法如下:

QPolygonF()
QPolygonF(arg_1:Sequence[Union[QPointF,QPoint]])

  用 QPolygon 的 append(QPoint) 方法可以添加点,用 insert(int,QPoint) 方法可以插入点,用 setPoint(int,QPoint) 方法可以更改点;用 QPolygonF 的 append(Union[QPointF,QPoint]) 方法可以添加点,用 insert(int,Union[QPointF,QPoint]) 方法可以插入点。

import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPen, QBrush
from PySide6.QtCore import QPointclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2.1、创建钢笔对象pen = QPen()# 2.2、设置钢笔的颜色pen.setColor("red")# 2.3、设置钢笔的宽度pen.setWidth(10)# 2.4、使用钢笔对象painter.setPen(pen)# 3、绘制点painter.drawPoint(QPoint(self.width() // 2, self.height() // 2))if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

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(QPoint) 方法、setP2(QPoint)setPoints(QPoint,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) 方法可以获取是否设置了抗锯齿算法,其中枚举参数 QPainter.RenderHint 可以取值如下:

QPainter.RenderHint.Antialiasing               # 启用抗锯齿
QPainter.RenderHint.TextAntialiasing           # 对文本进行抗锯齿
QPainter.RenderHint.SmoothPixmapTransform      # 使用平滑的像素图像算法
QPainter.RenderHint.LosslessImageRendering     # 用于PDF文档
import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter
from PySide6.QtCore import QPointclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2、绘制直线painter.drawLine(QPoint(0, 0), QPoint(self.width(), self.height()))# 3.抗锯齿painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

5.3、绘制折线

  绘制折线必须用两个点,即使两条折线的终点和起始点相同,每条折线也必须用两个点来定义。折线由多个折线段构成,绘制折线需要给出多个点,上个折线段的终点是下个折线段的起始点。

drawPolyline(arg__1:Sequence[QPoint]) -> None
drawPolyline(arg__1:Sequence[QPointF]) -> None
drawPolyline(polygon:Union[QPolygon, Sequence[QPoint], QRect]) -> None
drawPolyline(polygon:Union[QPolygonF, Sequence[QPointF], QRectF]) -> None
import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter
from PySide6.QtCore import QPointclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)p1 = QPoint(10, 10)p2 = QPoint(self.width() - 10, 10)p3 = QPoint(10, self.height() - 10)p4 = QPoint(self.width() - 10, self.height() - 10)# 2、绘制折线painter.drawPolyline([p1, p2, p3, p4])if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

5.4、绘制矩形

  QPainter 可以一次绘制一个矩形,也可以一次绘制多个矩形。

# 绘制单个矩形
drawRect(rect:QRect) -> None
drawRect(rect:Union[QRect, QRectF]) -> None
drawRect(x1:int, y1:int, w:int, h:int) -> None# 绘制多个矩形
drawRects(rectangles:Sequence[QRect]) -> None
drawRects(rectangles:Sequencep[QRectF]) -> None

  其中 drawRect(x1:int,y1:int,w:int,h:int) 方法中 x1 和 y1 参数确定左上角的位置,w 和 h 参数确定宽度和高度。

  圆角矩形是在矩形的基础上对 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     # 椭圆半径是相对于矩形边长的相对值
import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter
from PySide6.QtCore import QRect, Qtclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2.设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2、绘制矩形painter.drawRect(QRect(10, 10, self.width() - 20, self.height() // 2 - 20))# 3、绘制圆角矩形painter.drawRoundedRect(QRect(10, self.height() // 2, self.width() - 20, self.height() // 2 - 20), 50, 30, Qt.SizeMode.AbsoluteSize)if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

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
import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter
from PySide6.QtCore import QRectclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2、绘制椭圆painter.drawEllipse(QRect(10, 10, self.width() // 2 - 20, self.height() // 2 - 20))# 3.绘制扇形painter.drawPie(QRect(self.width() // 2, self.height() // 2, self.width() // 2 - 20, self.height() // 2 - 20), 45 * 16, 60* 16)if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

5.6、绘制多边形

  QPainter 绘制多边形和凸多边形的方法如下所示。

# 绘制多边形
drawPolygon(arg__1:Sequence[QPoint], arg__2:Qt.FillRule) -> None
drawPolygon(arg__1:Sequence[QPointF], arg__2:Qt.FillRule) -> None
drawPolygon(polygon:Union[QPolygon, Sequence[QPoint], QRect], fillRule:Qt.FillRule=Qt.OddEvenFill) -> None
drawPolygon(polygon:Union[QPolygonF, Sequence[QPointF], QPolygon, QRectF], fillRule:Qt.FillRule=Qt.OddEvenFill) -> None# 绘制凸多边形
drawConvexPolygon(polygon:Union[QPolygon, Sequence[QPoint], QRect]) -> None
drawConvexPolygon(polygon:Union[QPolygonF, Sequence[QPointF], QPolygon, QRectF]) -> None

  使用这些方法时,需要给出多边形或凸多边形的顶点,系统会自动在起始点和终止点之间建立直线,使多边形封闭。参数 fillRule 是 Qt.FillRule 的枚举类型,用于确定一个点是否在图形内部,在内部的区域可以进行填充。fillRule 可以取值如下:

Qt.FillRule.OddEvenFill
Qt.FillRule.WindingFill

  Qt.FillRule.OddEvenFill 是奇偶填充规则,要判断一个点是否在图形中,可以从该点向图形外引一条水平线,如果该水平线与图形的交点个数为奇数,那么该点在图形中。Qt.FillRule.WindingFill 是非零绕组填充规则,要判断一个点是否在图形中,可以从该点向图形外引一条水平线,如果该水平线与图形的边线相交,这个边线是顺时针绘制的,就记为 1,是逆时针绘制的就记为 -1,然后将所有数值相加,若结果不为 0,那么该点就在图形中。

填充规则

import sysfrom math import sin, cos, pi
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPen, QBrush
from PySide6.QtCore import QRect, Qt, QPointFclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2、设置钢笔pen = QPen()pen.setWidth(2)painter.setPen(pen)# 3、设置画刷brush = QBrush(Qt.BrushStyle.SolidPattern)painter.setBrush(brush)r = 100x = self.width() / 4y = self.height() / 4p1 = QPointF(r * cos(-90 * pi / 180) + x, r * sin(-90 * pi / 180) +y)p2 = QPointF(r * cos(-18 * pi / 180) + x, r * sin(-18 * pi / 180) +y)p3 = QPointF(r * cos(54 * pi / 180) + x, r * sin(54 * pi / 180) +y)p4 = QPointF(r * cos(126 * pi / 180) + x, r * sin(126 * pi / 180) +y)p5 = QPointF(r * cos(198 * pi / 180) + x, r * sin(198 * pi / 180) +y)# 4、绘制多边形painter.drawPolygon([p1, p2, p3, p4, p5], Qt.FillRule.OddEvenFill)offset = QPointF(self.width() / 2, 0)painter.drawConvexPolygon([p1 + offset, p2 + offset, p3 + offset, p4 + offset, p5 + offset])if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

六、绘制文本

  可以在指定位置绘制文本,绘制文本时,通常需要先用 setFont(QFont) 方法设置 QPainter 的字体。绘制文本的方法如下所示,所绘文本默认是反锯齿的。

drawStaticText(topLeftPosition:Union[QPoint, QPointF, QPainterPath.Element], staticText:QStaticText) -> None
drawStaticText(left:int, top:int, staticText:QStaticText) -> NonedrawText(p:Union[QPoint, QPointF, QPainterPath.Element], s:str) -> None
drawText(p:QPoint, s:str) -> None
drawText(r:Union[QRect, QRectF], flags:int, text:str) -> None
drawText(x:int, y:int, s:str) -> None
drawText(x:int, y:int, w:int, h:int, flags:int, text:str) -> None

  绘制文本可以用 drawStaticText() 方法,该方法比较快,且每次不用重新计算文本的排列位置。QStaticText 是静态文本类,用 QStaticText 类创建静态文本的方法是 QStaticText()QStaticText(str)。可以用 QStatciText 的 setText(str) 方法设置文本;用 setTextFormat(Qt.TextFormat) 方法设置静态文本的格式,参数 Qt.TextFormat 可取值如下:

Qt.TextFormat.PlainText
Qt.TextFormat.RichText
Qt.TextFormat.AutoText
Qt.TextFormat.MarkdownText
import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainterclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2.绘制文本painter.drawText(10, 100, "你好,世界!")if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

七、绘图路径

  为了将简单的图形组合成复杂且封闭的图形,需要用到绘图路径 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(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) -> NoneaddRegion(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                                  # 由当前路径的终点位置与给定路径的起始位置绘制直线

  路径是由多个图形构成的,每个图形中可能包括直线、贝塞尔曲线、弧、椭圆、多边形、矩形或文本。使用 moveTo() 方法把当前路径移到指定位置,作为绘图开始的起点位置,移动当前点会启用一个新的子路径,并自动封闭之前的路径。

  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                               # 如果包含指定的路径,则返回TruecontrolPointRect() -> 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]    # 将每个元素转换成QPolygonFtranslated(offset:Union[QPoint, QPointF]) -> QPainterPath               # 获取平移后的绘图路径
translated(dx:float, dy:float) -> QPainterPath                          # 获取平移后的绘图路径
import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainterPath, QPainter, QPen, QBrush, Qt
from PySide6.QtCore import QPointFclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建路径path = QPainterPath()center = QPointF(self.width() / 2, self.height() / 2)r = min(self.width() , self.height()) / 3# 2、将当前点移动到指定点,作为起始点path.moveTo(center)# 3、绘制圆弧path.arcTo(center.x() - r, center.y() - r, 2 * r, 2 * r, 0, 360)# 4、设置填充方式path.setFillRule(Qt.FillRule.WindingFill)# 5、创建绘画对象painter = QPainter(self)# 6、创建钢笔对象pen = QPen()pen.setWidth(5)pen.setColor(Qt.GlobalColor.black)# 7、使用钢笔对象painter.setPen(pen)# 8、创建画刷对象brush = QBrush(Qt.BrushStyle.SolidPattern)# 9、使用画刷对象painter.setBrush(brush)# 10、绘制路径painter.drawPath(path)super().paintEvent(event)if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

八、填充

  用 QPainter 绘图时,如果所绘制的图形是封闭的,且为 QPainter 设置了画刷,则系统自动在封闭的图形内填充画刷的图案,封闭的图形包括绘图路径、矩形、椭圆、多边形。除此之外,还可以为指定的矩形范围填充图案,此时不需要有封闭的边界线。

  QPainter 类的用来填充的常用方法如下:

# 为指定的路径填充颜色
fillPath(path:QPainterPath, brush:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, QGradient, QImage, QPixmap]) -> None# 用画刷填充指定的矩形区域
fillPath(path:Union[QRect, QRectF], brush:Union[QBrush, Qt.BrushStyle, Qt.GlobalColor, QColor, str, QGradient, QImage, QPixmap]) -> None
# 用颜色和渐变色填充指定的矩形区域
fillRect(x:int, y:int, w:int, h: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, w:int, h:int) -> NonesetBackground(bg:Union[QBrush, QColor, Qt.GlobalColor, QGradient]) -> None              # 设置背景色
background() -> QBrush                                                                  # 获取背景画刷
setBackgroundMode(mode:Qt.BGMode) -> None                                               # 设置背景模式
setBrushOrigin(arg__1:Union[QPoint, QPointF, QPainterPath.Element]) -> None             # 设置画刷的起始点
setBrushOrigin(x:int, y:int) -> None                                                    # 设置画刷的起始点
brushOrigin() -> None                                                                   # 获取起始点QPoint

  用 fillRect() 方法可以给指定的矩形区域绘制填充颜色,这时无须封闭的空间,也不会绘制出轮廓;用 eraseRect() 方法可以擦除矩形区域的填充。

  用 setBackgroundMode(Qt.BGMode) 方法设置背景的模式,其中参数 Qt.BGMode 可以取值如下:

Qt.BGMode.TransparentMode    # 透明模式
Qt.BGMode.OpaqueMode         # 不透明模式

  用 setBackground(Union[QBrush,QColor,Qt.GlobalColor,QGradient]) 方法设置背景色,背景色只有在不透明模式下才起作用。

  用 setBrushOrigin(Union[QPointF,QPoint])setBrushOrigin(int,int)setBrushOrigin(QPoint) 方法设置画刷的起始点,起始点会影响纹理、渐变色的布局。

import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter
from PySide6.QtGui import QLinearGradient, QPen, QBrush
from PySide6.QtCore import QPointF, Qtclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2.1、使用线性渐变充当文字颜色linear_1 = QLinearGradient(QPointF(0, 0), QPointF(self.width(), self.height()))# 2.2、设置颜色linear_1.setStops([(0, Qt.GlobalColor.red), (0.3, Qt.GlobalColor.yellow), (0.6, Qt.GlobalColor.green), (1, Qt.GlobalColor.blue)])# 2.3、设置扩展模式linear_1.setSpread(QLinearGradient.Spread.ReflectSpread)# 2.4、用线性渐变定义画刷brush_1 = QBrush(linear_1)# 3、创建钢笔对象pen = QPen()pen.setBrush(brush_1)painter.setPen(pen)# 4、创建字体对象font = painter.font()font.setFamily("楷体")font.setBold(True)font.setPointSize(50)# 5、使用字体对象painter.setFont(font)# 6、设置背景模式不透明painter.setBackgroundMode(Qt.BGMode.OpaqueMode)# 7.1、使用线性渐变充当文字颜色linear_2 = QLinearGradient(QPointF(0, 0), QPointF(self.width(), self.height()))# 7.2、设置颜色linear_2.setStops([(0, Qt.GlobalColor.blue), (0.3, Qt.GlobalColor.green), (0.6, Qt.GlobalColor.red), (1, Qt.GlobalColor.white)])# 7.3、设置扩展模式linear_2.setSpread(QLinearGradient.Spread.ReflectSpread)# 7.4、用线性渐变定义画刷brush_2 = QBrush(linear_2)# 8、设置背景画刷painter.setBackground(brush_2)# 9、设置画刷的起始点painter.setBrushOrigin(0, 0)# 10、绘制字体painter.drawText(100, 100, "你好,世界!")if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

九、绘制图像

  QPainter 还可以把 QPixmap、QImage 和 QPicture 图像直接绘制在绘图设备上。

  绘制 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(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
drawTiledPixmap(x:int, y:int, w:int, h:int, pm:Union[QPixmap, QImage, str], sx:int=0, sy:int=0) -> 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.OpaqueHint;参数 QPainter.PixmapFragment 的创建方法如下:

QPainter.PixmapFragment.create(pos:QPointF,sourceRect:QRectF,scaleX=1,scaleY=1,rotation=0,opacity=1)

  其中 pos 是图像绘制地点,sourceRect 是截取的图像的部分区域,scaleX 和 scaleY 是缩放比例,rotation 是旋转角度,opacity 是不透明度值。

  绘制 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

  对于 QPicture 图像,只能在绘图设备的指定点上按照原始尺寸进行绘制。绘制 QPicture 图像的方法如下:

drawPicture(p:Union[QPointF, QPoint, QPainterPath.Element], picture:Union[QPicture,int]) -> None
drawPicture(x:int, y:int, picture:Union[QPicture,int]) -> None
import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPixmapclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2、创建图像对象pixmap = QPixmap("./1.jpg")# 3、绘制图像painter.drawPixmap(self.rect(), pixmap)if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

十、裁剪区域

  当所绘图形比较大时,若只想显示绘图上的一部分区域的内容,其他区域的内容不显示,就需要使用裁剪区域。用 QPainter 设置裁剪区域的方法下所示:

setClipping(enable:bool) -> None                                                                                # 设置是否启动裁剪区域
hasClipping() -> bool                                                                                           # 获取是否有裁剪区域
setClipPath(path:QPainterPath, op:Qt.ClipOperation=Qt.ReplaceClip) -> None                                      # 用路径设置裁剪区域
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                             # 用矩形框设置裁剪区域
setClipRegion(arg_1:Union[QRegion, QBitmap, QPolygon, QRect], op:Qt.ClipOperation=Qt.ReplaceClip) -> None       # 用QRegion设置裁剪区域
clipBoundingRect() -> QRectF                                                                                    # 获取裁剪区域的边界矩形
clipPath() -> QPainterPath                                                                                      # 获取裁剪区域的路径
clipRegion() -> QRegion                                                                                         # 获取裁剪区域

  其中参数 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(Sequence[QRect]) 方法可以设置多个矩形区域,多个矩形之间不能相互交叉,处于同一层的矩形必须有相同的高度,而不能连在一起,多个矩形可以合并成一个矩形。多个矩形首先按 y 值以升序排列,其次按 x 值以升序排列。

import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPixmap, QRegion
from PySide6.QtCore import QRectclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2、创建图像对象pixmap = QPixmap("./1.jpg")# 3、设置是否启动裁剪区域painter.setClipping(True)# 4、裁剪区域rect_1 = QRect(self.width() // 20, self.height() // 10, self.width() // 10 * 4, self.height() // 10 * 3)rect_2 = QRect(self.width() // 20, self.height() // 10 * 5, self.width() // 10 * 4, self.height() // 10 * 3)rect_3 = QRect(self.width() // 20 * 11, self.height() // 10, self.width() // 10 * 4, self.height() // 10 * 3)rect_4 = QRect(self.width() // 20 * 11, self.height() // 10 * 5, self.width() // 10 * 4, self.height() // 10 * 3)region_1 = QRegion(rect_1)                                  # 矩形裁剪区域region_2 = QRegion(rect_2)                                  # 矩形裁剪区域region_3 = QRegion(rect_3, t=QRegion.RegionType.Ellipse)    # 椭圆裁剪区域region_4 = QRegion(rect_4, t=QRegion.RegionType.Ellipse)    # 椭圆裁剪区域# 5、裁剪区域的布尔运算,并集运算region = region_1.united(region_2).united(region_3).united(region_4)# 6、用QRegion设置裁剪区域painter.setClipRegion(region)# 7、绘制图像painter.drawPixmap(self.rect(), pixmap)if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

十一、图形合成

  图形合成是指当绘制新图形时,绘图设备上已经存在旧图形,对新图形和旧图形进行处理的方法。图形合成是基于像素,将旧图形的颜色值和 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_DestinationOverQPainter.CompositionMode.CompositionMode_Clear
QPainter.CompositionMode.CompositionMode_Xor
import sysfrom PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QPixmap
from PySide6.QtCore import QRectFclass MyWidget(QWidget):def __init__(self):# 1、调用父类的__init__()方法super().__init__()# 2、设置窗口对象大小self.resize(700, 500)def paintEvent(self, event):# 1、创建绘图对象painter = QPainter(self)# 2、创建图像对象pixmap = QPixmap("./1.jpg")# 3、绘制图像painter.drawPixmap(self.rect(), pixmap)# 4、设置图像的合成方式painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceAtop)# 5、获取窗口的取行rect = QRectF(0, 0, self.width(), self.height())# 6.绘制图标ico = QPixmap("./1.ico")painter.drawPixmap(10, 10, ico)if __name__ == "__main__":# 1、创建一个QApplication类的实例app = QApplication(sys.argv)# 2、创建一个窗口window = MyWidget()# 3、展示窗口window.show()# 4、进入程序的主循环并通过exit()函数确保主循环安全结束sys.exit(app.exec())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/871778.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go 反射 の 应用场景

两年前曾经写过一篇博客,是关于反射基本概念的 Go 反射 の 基本概念,之后对其再也没有更深入的学习,主要因为 反射主要应用在一些基本库中,而在平时的项目开发中几乎用不到。本文结合一个sql构造器的应用案例,深入的了解一下反射的应用场景。 什么是反射射就是程序在运行时…

中考英语优秀范文-热点话题-传统文化-010 Mid-Autumn Festival 中秋节

1 写作要求 中秋节是我国的传统节日,随着经济的发展和时代的变迁,中秋节依然在我们国人心中有着重要的位置。在中秋节,人们望着天上的明月,守望膜拜,吃着月饼,寄托情怀,这个节日更多地被赋予了思念亲人的色彩,祈求团圆和幸福。过去的中秋节有没有特别让你难忘的事情发生…

AtCoder Beginner Contest 389

A - 9x9 题意一位数的乘法思路模拟代码点击查看代码 #include <bits/stdc++.h> using namespace std; #define int long long typedef pair<int, int> pii;const int mxn = 1e6 + 5;void solve() {string s;cin >> s;cout << (s[0] - 0) * (s[2] - 0) …

2025 开局,我的身体给我上了一课

2025年,我被身体狠狠地上了一课!最终不得不放弃?这不仅是一个关于放弃的故事,更是一个关于接受和改变的过程背景 说实话,时间这东西真的太快了,一年就过去了。 每到这个时候,大家都会写年终总结:这一年,做了什么?也许是因为找不到清晰的答案,干脆就摆烂,都懒得写了…

VS Code远程连接服务器

VS Code远程连接服务器 总体分为两步:在远程服务器安装SSH协议实现软件OpenSSH 在VS Code安装Remote-SSH插件,然后利用该插件登录远程服务器在远程服务器安装SSH协议实现软件 查看是否安装了SSH协议实现软件 dpkg -l | grep ssh如果没有安装,可以通过以下命令安装OpenSSH的客…

Prim最小生成树算法

Prim最小生成树算法 首先给出最小生成树的概念:把给定的无向图中转换成一棵树,且树的边权和最小 Prim算法基于贪心的思想,每次在图中选取距离最小生成树最近的点加入树 首先给出朴素的模板算法: struct edge{int v,w; };int n,m; vector<edge> e[5010]; int dis[5010…

同余前缀和

1 #include<iostream>2 using namespace std;3 4 /*5 原题地址:https://www.luogu.com.cn/problem/P31316 农夫约翰的 \( N \) 头奶牛站在一排,就像它们时不时做的那样。每头奶牛都有一个唯一的整数ID号,7 这样农夫约翰可以区分它们。农夫约翰想要给一组连…

1.MySql基础架构之SQL语句的执行

1.MySQL数据库的整体架构(i)连接器:连接器负责与客户端建立连接,获取权限、维持和管理连接。连接命令中的mysql是客户端工具,用来建立服务端连接。在完成经典的TCP握手后,连接器就要开始认证你的身份,这个时候用的就是你输入的用户名和密码。 ​ 如果用户名密码认证通过…

ATF引导启动流程整理-Part2:BL1引导启动流程整理

接上一章的介绍,本文详细整理一下 BL1 阶段的流程 Ch3: ATF启动流程 上面一章简单的介绍了 ATF的隔离和划分,下面就介绍一下使用 ATF 初始启动的流程。ARM v8的启动流程包含多个阶段,典型的官方定义的标志阶段包括 BL1、BL2、BL31、BL32、BL33,根据不同需求这些阶段可以添加…

推荐一款非常好用的在线 SSH 管理工具

前言 SSH工具在远程连接、文件传输、远程管理和增强安全性等方面发挥着重要作用,是我们开发人员和系统管理员不可或缺的工具。今天大姚给大家推荐一款非常好用的在线 SSH 管理工具:Xterminal。工具介绍 Xterminal一个好用的在线SSH、SFTP工具,支持跨平台(Windows、Linux、M…

代码随想录——动态规划背包问题总结

https://www.programmercarl.com/背包总结篇.html#听说背包问题很难-这篇总结篇来拯救你了

DASCTF --wp--web

1、Rank-lSsti的报错查询cycler没用被禁用,很常规的到达popen阶段{{cycler.__init__.__globals__.__builtins__[__import__](os).popen(ls).read()}}正常在浏览器中无法查看,使用pythonimport requestswith requests.Session() as session: url_phone = http://139.155.12…