QCanvasPath Class
QCanvasPath 是QCanvasPainter 的原生路径格式。更多内容...
| 标题: | #include <QCanvasPath> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS CanvasPainter) target_link_libraries(mytarget PRIVATE Qt6::CanvasPainter) |
| 自: | Qt 6.11 |
公共函数
| QCanvasPath() | |
| QCanvasPath(qsizetype commandsSize, qsizetype commandsDataSize = -1) | |
| QCanvasPath(const QCanvasPath &path) | |
| QCanvasPath(QCanvasPath &&other) | |
| ~QCanvasPath() | |
(since 6.12) void | addPath(QStringView svgPath, const QTransform &transform = QTransform()) |
| void | addPath(const QCanvasPath &path, const QTransform &transform = QTransform()) |
| void | addPath(const QCanvasPath &path, qsizetype start, qsizetype count, const QTransform &transform = QTransform()) |
| void | arc(qreal centerX, qreal centerY, qreal radius, qreal a0, qreal a1, QCanvasPainter::PathWinding direction = QCanvasPainter::PathWinding::ClockWise, QCanvasPainter::PathConnection connection = QCanvasPainter::PathConnection::Connected) |
| void | arc(QPointF centerPoint, qreal radius, qreal a0, qreal a1, QCanvasPainter::PathWinding direction = QCanvasPainter::PathWinding::ClockWise, QCanvasPainter::PathConnection connection = QCanvasPainter::PathConnection::Connected) |
| void | arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius) |
| void | arcTo(QPointF point1, QPointF point2, qreal radius) |
| void | beginHoleSubPath() |
| void | beginSolidSubPath() |
| void | bezierCurveTo(qreal cp1X, qreal cp1Y, qreal cp2X, qreal cp2Y, qreal x, qreal y) |
| void | bezierCurveTo(QPointF controlPoint1, QPointF controlPoint2, QPointF endPoint) |
| void | circle(qreal x, qreal y, qreal radius) |
| void | circle(QPointF centerPoint, qreal radius) |
| void | clear() |
| void | closePath() |
| qsizetype | commandsCapacity() const |
| qsizetype | commandsDataCapacity() const |
| qsizetype | commandsDataSize() const |
| qsizetype | commandsSize() const |
| QPointF | currentPosition() const |
| void | ellipse(qreal x, qreal y, qreal radiusX, qreal radiusY) |
| void | ellipse(const QRectF &rect) |
| bool | isEmpty() const |
| void | lineTo(QPointF point) |
| void | lineTo(qreal x, qreal y) |
| void | moveTo(QPointF point) |
| void | moveTo(qreal x, qreal y) |
| QPointF | positionAt(qsizetype index) const |
| void | quadraticCurveTo(qreal cpX, qreal cpY, qreal x, qreal y) |
| void | quadraticCurveTo(QPointF controlPoint, QPointF endPoint) |
| void | rect(qreal x, qreal y, qreal width, qreal height) |
| void | rect(const QRectF &rect) |
| void | reserve(qsizetype commandsSize, qsizetype commandsDataSize = -1) |
| void | roundRect(qreal x, qreal y, qreal width, qreal height, qreal radius) |
| void | roundRect(qreal x, qreal y, qreal width, qreal height, qreal radiusTopLeft, qreal radiusTopRight, qreal radiusBottomRight, qreal radiusBottomLeft) |
| void | roundRect(const QRectF &rect, qreal radius) |
| void | roundRect(const QRectF &rect, qreal radiusTopLeft, qreal radiusTopRight, qreal radiusBottomRight, qreal radiusBottomLeft) |
| void | setPathWinding(QCanvasPainter::PathWinding winding) |
| QCanvasPath | sliced(qsizetype start, qsizetype count, const QTransform &transform = QTransform()) const |
| void | squeeze() |
| void | swap(QCanvasPath &other) |
| operator QVariant() const | |
| QCanvasPath & | operator=(QCanvasPath &&other) |
| QCanvasPath & | operator=(const QCanvasPath &path) |
相关的非成员
| bool | operator!=(const QCanvasPath &lhs, const QCanvasPath &rhs) |
| bool | operator==(const QCanvasPath &lhs, const QCanvasPath &rhs) |
详细说明
绘图路径是由多个图形构建块(如矩形、椭圆、直线和曲线)组成的对象。QCanvasPath API 与QCanvasPainter 的路径绘制功能相匹配,因此可以轻松地在直接绘制和路径绘制之间切换代码。 使用 QCanvasPath 的主要原因是避免重新创建在渲染的每一帧中都使用的静态路径,并可能启用路径相关渲染数据(例如由此生成的顶点和索引数据)的缓存,而不是在每次填充或描边路径时都重新生成这些数据。
与QPainterPath 相比,QCanvasPath在渲染方面进行了更多优化,但路径比较或调整的功能较少。具体而言:
- 不提供两个路径之间的相交或差集运算方法。
- 没有用于平移路径的方法。
- 没有添加文本的方法。
从功能角度来看,QCanvasPath 更类似于 HTML Canvas的 Path2D,但增加了一些功能,且其 API 与QCanvasPainter 保持一致。
路径组与缓存
通过 QCanvasPath 绘制路径可让引擎缓存路径几何信息(顶点)。这虽然能提升静态路径的性能,但也可能增加 CPU 和 GPU 的内存消耗。
当使用将QCanvasPath 作为参数的fill()或stroke()绘制路径时,可以将pathGroup 作为第二个参数进行设置。
默认情况下,pathGroup 的值为-1 ,这意味着系统不会尝试缓存路径数据,因此渲染过程与直接使用 beginPath() 绘制路径、随后执行路径定义命令,最后进行填充或描边时几乎完全相同。
将 `pathGroup ` 设置为 `0 ` 或更高的数值,将启用路径生成的几何体的缓存和复用。将路径组织成路径组可以有效优化渲染性能和内存使用。属于同一组且经常同时变化的路径应置于同一组中,以获得最佳效果。
当路径发生变化时,其数据(即使已被缓存)也会自动更新。导致路径组几何图形更新的情况包括:
- 清除路径元素或添加新元素。
- 更改描边线宽(QCanvasPainter::setLineWidth(),适用于描边)。
- 调整抗锯齿程度(QCanvasPainter::setAntialias(),同时适用于填充和描边)。
- 更改线条端点或线条连接类型(QCanvasPainter::setLineCap()、QCanvasPainter::setLineJoin(),适用于描边)。
- 更改winding enforce (同时适用于填充和描边)。
- 更改high quality stroking (同时适用于填充和描边)。
请注意,更改状态变换(QCanvasPainter::transform()、QCanvasPainter::rotate() 等)不会使路径失效,因此移动、缩放或旋转缓存的路径非常高效。
举个例子,考虑一个包含大量命令的 QCanvasPathp 。由于 CPU 端需要执行大量工作,因此对该路径进行描边或填充p 可能是一项开销很大的操作。 在每一帧中,每次执行描边或填充操作时,都可能需要重新生成顶点数据并将其上传到 GPU 缓冲区。当路径是静态的,而我们只想在每一帧中尽可能高效地反复绘制它时,这种做法并不理想。
当指定路径组时(例如将stroke(p) 替换为stroke(p, 5) ),渲染器可选择为路径p 以及在描边或填充命令中指定了相同组(5 )的任何其他路径,维护专用的顶点和索引缓冲区。
假设路径p (即 QCanvasPath 中的命令)保持不变,则反复对该路径进行填充或描边将变得非常高效,因为所有数据都已存在于专用于路径组5 的 GPU 缓冲区中。变换操作同样高效,因为在缓存路径组的情况下,变换是在顶点着色器中进行的,而非在几何体本身上进行。
在以下代码片段中,当m_path 足够复杂时,其命令不会发生变化,且每帧都以相同的描边宽度、抗锯齿程度等参数进行描边,此时以下做法将比不使用路径组高效得多:
// m_path is QCanvasPath with lots of commands in it
const int pathGroup = 5;
// in every frame:
painter->stroke(m_path, pathGroup);
// ... other draw commands
painter->translate(100, 0);
painter->stroke(m_path, pathGroup);
// ... other draw commands当第二次、第三次及后续绘制m_path 时,与不使用路径组相比,渲染开销将非常低,因为CPU端无需进行任何路径几何体处理。通过平移来改变变换并不会使缓存的路径组数据失效,因此经过平移后的stroke()调用速度同样快。
如果上述相关状态之一发生变化会怎样?例如,如果路径使用两种不同的描边宽度进行绘制:
// m_path is QCanvasPath with lots of commands in it
const int pathGroup = 5;
// in every frame:
painter->setStrokeWidth(4);
painter->stroke(m_path, pathGroup);
// ... other draw commands
painter->translate(100, 0);
painter->setStrokeWidth(8);
painter->stroke(m_path, pathGroup);
// ... other draw commands这仍然非常高效,因为路径顶点数据会被缓存并同时用于笔画宽度为 4 和 8 的情况,但资源占用会略有增加,因为路径组5 的 GPU 缓冲区现在将同时包含笔画宽度为 4 和 8 的路径几何体版本。
可以将路径组视为一种缓存机制:其中路径组值被视为一级缓存键,而 QCanvasPath 对象、抗锯齿程度、渲染提示,以及在描边情况下,描边宽度、线端和线连接则构成二级缓存键 (在路径组内)。
更改路径命令(即 QCanvasPath 中的元素)始终代价高昂,因为这总会导致 CPU 和 GPU 端相关数据的重建。 举一个比较极端的例子:如果一个 QCanvasPath 在每一帧中都会更改其命令,那么对于该特定路径而言,使用路径组(甚至 QCanvasPath)就没有意义了,因为与通过QCanvasPainter 函数直接绘制路径相比,它没有任何好处。
在路径组不再用于绘制,或者应用程序希望尽可能释放内存的情况下,可以通过调用 `QCanvasPainter::removePathGroup()` 来释放缓存。通常不需要这样做,因为缓存的路径会在绘制器的析构函数中自动释放。
另请参阅 QCanvasPainter::addPath() 和QCanvasPainter::removePathGroup()。
成员函数文档
QCanvasPath::QCanvasPath()
构建一个空路径。
[explicit] QCanvasPath::QCanvasPath(qsizetype commandsSize, qsizetype commandsDataSize = -1)
构建一个空路径,为commandsSize 个命令分配空间,并可选地为commandsDataSize 的数据分配空间。如果未提供commandsDataSize 参数,系统会自动为2 * commandsSize 的数据预留空间,当路径命令为直线时(moveTo()、lineTo()、rect()),这是最优的数据量。
预留正确的空间是路径创建和内存使用的一种优化措施。这并非强制要求,因为在向路径添加命令时,系统会自动确保有足够的空间。
另请参阅 reserve()。
QCanvasPath::QCanvasPath(const QCanvasPath &path)
构建一条路径,该路径是给定path 的副本。
[noexcept] QCanvasPath::QCanvasPath(QCanvasPath &&other)
从other 创建一个新的QCanvasPath对象。
[noexcept] QCanvasPath::~QCanvasPath()
删除该路径。
[since 6.12] void QCanvasPath::addPath(QStringView svgPath, const QTransform &transform = QTransform())
将svgPath 添加到该路径中,可选地使用transform 来修改路径点。如果已知路径的估计大小,请考虑在此之前调用reserve()。
![]() | |
有关此格式的更多详细信息,请参阅W3C SVG 路径数据。
该函数于 Qt 6.12 中引入。
void QCanvasPath::addPath(const QCanvasPath &path, const QTransform &transform = QTransform())
将path 添加到该路径中,可选地使用transform 来修改路径节点。当未提供transform (或其值为单位矩阵)时,由于该操作会复用路径数据,因此执行速度非常快。
void QCanvasPath::addPath(const QCanvasPath &path, qsizetype start, qsizetype count, const QTransform &transform = QTransform())
将path 添加到当前路径中,从start 处的命令开始,并包含count 个命令。可选地使用transform 来修改路径节点。系统会检查start 和count 的范围,以确保访问的命令数量不超过QCanvasPath::commandsSize()。如果路径不应从当前路径位置继续,请先调用moveTo(),并传入path.positionAt(start - 1) 。
void QCanvasPath::arc(qreal centerX, qreal centerY, qreal radius, qreal a0, qreal a1, QCanvasPainter::PathWinding direction = QCanvasPainter::PathWinding::ClockWise, QCanvasPainter::PathConnection connection = QCanvasPainter::PathConnection::Connected)
创建一个以QPointF (centerX ,centerY )为中心的弧,其radius 为给定值,起始角度为a0 弧度,结束角度为a1 弧度。该弧的跨度为给定的direction 。当connection 为NotConnected 时,将关闭前一条路径并开始一条新的子路径。
void QCanvasPath::arc(QPointF centerPoint, qreal radius, qreal a0, qreal a1, QCanvasPainter::PathWinding direction = QCanvasPainter::PathWinding::ClockWise, QCanvasPainter::PathConnection connection = QCanvasPainter::PathConnection::Connected)
创建一个以centerPoint 为中心的弧,其radius 为给定值,起始角度为a0 弧度,结束角度为a1 弧度。该弧的跨度为给定的direction 。当connection 为NotConnected 时,前一条路径将闭合,并开始一条新的子路径。
这是一个重载函数。
void QCanvasPath::arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius)
使用点QPointF (x1 ,y1 )和QPointF (x2 ,y2 ),并采用给定的radius ,绘制一条弧。
void QCanvasPath::arcTo(QPointF point1, QPointF point2, qreal radius)
使用点point1 和point2 ,并根据给定的radius 创建一个弧。
这是一个重载函数。
void QCanvasPath::beginHoleSubPath()
开始一个孔子路径。这相当于setPathWinding(QCanvasPainter::PathWinding::ClockWise))
另请参阅 beginSolidSubPath()。
void QCanvasPath::beginSolidSubPath()
开始一个完整的子路径。这等同于setPathWinding(QCanvasPainter::PathWinding::CounterClockWise))
另请参阅 beginHoleSubPath()。
void QCanvasPath::bezierCurveTo(qreal cp1X, qreal cp1Y, qreal cp2X, qreal cp2Y, qreal x, qreal y)
在当前位置与由x 和y 指定的终点之间添加一条三次贝塞尔曲线,使用由cp1X 、cp1Y 、cp2X 和cp2Y 指定的控制点。
添加曲线后,当前位置将更新为曲线的终点。
void QCanvasPath::bezierCurveTo(QPointF controlPoint1, QPointF controlPoint2, QPointF endPoint)
在当前位置与给定的endPoint 之间,使用由controlPoint1 和controlPoint2 指定的控制点,添加一条三次贝塞尔曲线。
曲线添加完成后,当前位置将更新为该曲线的终点。
这是一个重载函数。
void QCanvasPath::circle(qreal x, qreal y, qreal radius)
将一个圆添加到路径中,该圆的圆心位于QPointF (x ,y ),半径为给定的radius 。
void QCanvasPath::circle(QPointF centerPoint, qreal radius)
向路径中添加一个圆,其圆心位于centerPoint ,半径为给定的radius 。
这是一个重载函数。
void QCanvasPath::clear()
清除路径命令和数据。
当路径命令发生变化时,调用此函数以重新生成路径。这不会影响内存使用,若需管理内存,请使用reserve() 和squeeze()。
void QCanvasPath::closePath()
通过绘制一条连接至当前子路径起点的直线来结束该子路径,并自动开始绘制新路径。
qsizetype QCanvasPath::commandsCapacity() const
返回路径中命令的容量。
另请参阅 commandsDataCapacity() 和reserve()。
qsizetype QCanvasPath::commandsDataCapacity() const
返回路径中命令数据的容量。
另请参阅 commandsCapacity() 和reserve()。
qsizetype QCanvasPath::commandsDataSize() const
返回路径中命令数据的数量。
命令数据基本上指的是命令所需的点。
注意:某些 路径元素需要多个数据点。例如,closePath 需要0 、moveTo 和lineTo 需要2 、bezierCurveTo 需要 6 个数据点,而roundRect 需要34 个数据点。
qsizetype QCanvasPath::commandsSize() const
返回路径中的命令数量。
注意:某些 路径元素需要多个命令。例如,moveTo 和lineTo 需要1 个命令,bezierCurveTo 需要6 个命令,roundRect 需要10 个命令。
QPointF QCanvasPath::currentPosition() const
返回路径的当前位置。即上一个路径命令(moveTo 、lineTo 、bezierCurveTo 等)结束时的位置。当路径为空时,返回 (0.0, 0.0)。
void QCanvasPath::ellipse(qreal x, qreal y, qreal radiusX, qreal radiusY)
创建一个以 (x,y) 为中心的椭圆,其半径由radiusX 和radiusY 定义,并将其作为闭合子路径添加到路径中。
void QCanvasPath::ellipse(const QRectF &rect)
在矩形rect 内创建一个椭圆,并将其作为闭合子路径添加到路径中。
这是一个重载函数。
bool QCanvasPath::isEmpty() const
当路径为空时返回 true。
另请参阅 clear 。
void QCanvasPath::lineTo(QPointF point)
从当前位置到指定的point 绘制一条直线。绘制完成后,当前位置将更新为该直线的终点。
这是一个重载函数。
void QCanvasPath::lineTo(qreal x, qreal y)
从当前位置到点 (x,y) 绘制一条直线。
这是一个重载函数。
void QCanvasPath::moveTo(QPointF point)
将当前点移动到指定的point ,同时隐式地开始一个新的子路径并关闭之前的子路径。
这是一个重载函数。
void QCanvasPath::moveTo(qreal x, qreal y)
将当前位置移动到 (x,y),并开始一个新的子路径,同时隐式关闭之前的路径。
这是一个重载函数。
QPointF QCanvasPath::positionAt(qsizetype index) const
返回路径在index 中的位置。这指的是path命令(moveTo 、lineTo 、bezierCurveTo 等)在index 中的位置。索引值必须介于0 和commandsSize() - 1之间。当路径为空时,返回(0.0, 0.0)。
void QCanvasPath::quadraticCurveTo(qreal cpX, qreal cpY, qreal x, qreal y)
在当前点与端点(x ,y )之间添加一条二次贝塞尔曲线,其控制点由(cpX ,cpY )指定。
void QCanvasPath::quadraticCurveTo(QPointF controlPoint, QPointF endPoint)
在当前位置与给定的endPoint 之间添加一条二次贝塞尔曲线,其控制点由controlPoint 指定。
这是一个重载函数。
void QCanvasPath::rect(qreal x, qreal y, qreal width, qreal height)
创建一个矩形,其位置为QPointF (x ,y ),并采用给定的width 和height 。
void QCanvasPath::rect(const QRectF &rect)
创建一个由rect
这是一个重载函数。
void QCanvasPath::reserve(qsizetype commandsSize, qsizetype commandsDataSize = -1)
在QCanvasPath 的内部内存中预留指定大小的空间。
尝试为至少commandsSize 条命令和commandsDataSize 个数据点分配内存。某些路径元素需要多条命令,请参见commandsSize() 和commandsDataSize()。
如果未指定commandsDataSize ,则会自动为2 * commandsSize 数量的数据预留空间,当路径命令为直线时(如moveTo()、lineTo()、rect(),这是最优数量。
预留正确的空间是路径创建和内存使用的一项优化措施。这并非强制要求,因为在向路径中添加命令时,系统会自动确保有足够的空间。
另请参阅 squeeze(),commandsCapacity() 和commandsDataCapacity()。
void QCanvasPath::roundRect(qreal x, qreal y, qreal width, qreal height, qreal radius)
将给定的矩形x 、y 、width 、height (带圆角)添加到路径中。这些圆角为四分之一圆,其半径为给定的radius 。
void QCanvasPath::roundRect(qreal x, qreal y, qreal width, qreal height, qreal radiusTopLeft, qreal radiusTopRight, qreal radiusBottomRight, qreal radiusBottomLeft)
将具有圆角的矩形x 、y 、width 、height 添加到路径中。这些圆角分别是半径为radiusTopLeft 、radiusTopRight 、radiusBottomRight 和radiusBottomLeft 的四分之一圆。
void QCanvasPath::roundRect(const QRectF &rect, qreal radius)
将给定的矩形rect (带圆角)添加到路径中。圆角为四分之一圆,其参数由radius 指定。
这是一个重载函数。
void QCanvasPath::roundRect(const QRectF &rect, qreal radiusTopLeft, qreal radiusTopRight, qreal radiusBottomRight, qreal radiusBottomLeft)
将矩形rect (带圆角)添加到路径中。这些圆角分别是半径分别为radiusTopLeft 、radiusTopRight 、radiusBottomRight 和radiusBottomLeft 的四分之一圆。
这是一个重载函数。
void QCanvasPath::setPathWinding(QCanvasPainter::PathWinding winding)
将当前子路径winding 设置为QCanvasPainter::CounterClockWise (默认)或QCanvasPainter::ClockWise 。CounterClockWise绘制实心子路径,而ClockWise绘制孔洞。
QCanvasPath QCanvasPath::sliced(qsizetype start, qsizetype count, const QTransform &transform = QTransform()) const
返回一个新路径,其中包含该路径中的命令,从start 处的命令开始,并包含count 数量的命令,可选地使用transform 来更改路径节点。
系统会检查start 和count 的范围,以确保访问的命令数量不超过commandsSize()。如果start 处的命令不是MoveTo ,则将第一个命令替换为MoveTo ,以便该切片成为一个独立的路径。
void QCanvasPath::squeeze()
释放除存储路径命令和数据外不再需要的内存。这可用于在调用reserve() 之后减少内存占用。
通常无需使用此方法,但在因预留或添加大量元素(如lineTo 、bezierCurveTo 等)导致路径大小过大,且预计未来路径大小将大幅缩小时,先调用reserve() 再调用squeeze() ,可释放部分内存。
另请参阅 reserve()。
[noexcept] void QCanvasPath::swap(QCanvasPath &other)
将此路径与other 互换。此操作速度极快,且绝不会失败。
QCanvasPath::operator QVariant() const
将路径作为QVariant 返回。
[noexcept] QCanvasPath &QCanvasPath::operator=(QCanvasPath &&other)
将other 通过Move-assigns操作赋值给此QCanvasPath 实例。
QCanvasPath &QCanvasPath::operator=(const QCanvasPath &path)
将给定的path 分配给此路径,并返回对此路径的引用。
相关的非成员
[noexcept] bool operator!=(const QCanvasPath &lhs, const QCanvasPath &rhs)
如果路径lhs 与rhs 不一致,则返回true ;否则返回false 。
另请参阅 operator==()。
[noexcept] bool operator==(const QCanvasPath &lhs, const QCanvasPath &rhs)
如果路径lhs 等于rhs ,则返回true ;否则返回false 。
另请参阅 operator!=()。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.
