一、描述
1、绘制器路径是由许多图形构造块(例如矩形,椭圆形,直线和曲线)组成的对象。可以在封闭的子路径中将构建块连接起来。封闭的路径具有一致的起点和终点。或者它们可以作为未封闭的子路径(例如直线和曲线)独立存在。
2、QPainterPath对象可用于填充,概述和裁剪。与常规绘图操作相比,画家路径的主要优势在于,复杂的形状只需要创建一次即可。仅使用QPainter::drawPath()函数的调用就可以绘制它们多次。
二、类型成员
1、QPainterPath::ElementType:该枚举描述了用于连接子路径中的顶点的元素的类型。
- MoveToElement:新的子路径。
- LineToElement:一条线。
- CurveToElement:一条曲线。
- CurveToDataElement:描述CurveToElement元素中的曲线所需的额外数据。
三、内部类:QPainterPath::Element
QPainterPath::Element类指定子路径的位置和类型。
enum ElementType {
MoveToElement,
LineToElement,
CurveToElement,
CurveToDataElement
};
class Element {
public:
qreal x;
qreal y;
ElementType type;
bool isMoveTo() const { return type == MoveToElement; }
bool isLineTo() const { return type == LineToElement; }
bool isCurveTo() const { return type == CurveToElement; }
operator QPointF () const { return QPointF(x, y); }
bool operator==(const Element &e) const
{
return qFuzzyCompare(x, e.x)&& qFuzzyCompare(y, e.y) && type == e.type;
}
inline bool operator!=(const Element &e) const
{
return !operator==(e);
}
};
构造QPainterPath对象后,可以将诸如直线和曲线之类的子路径添加到路径中(添加直线 = 创建QPainterPath::LineToElement组件。添加曲线 = 创建QPainterPath::CurveToElement组件)。
直线和曲线从currentPosition()延伸到作为参数传递的位置。调用moveTo()函数 = 创建QPainterPath::MoveToElement组件。
四、成员函数
1、void addEllipse(const QRectF &boundingRectangle)
void addEllipse(const QPointF ¢er, qreal rx, qreal ry)
添加一个椭圆,参数为椭圆的外接矩形 / 参数为椭圆的外接矩形的中心和宽高。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setPen(QPen(Qt::cyan, 3, Qt::DashDotLine));
QPainterPath myPath;
myPath.addEllipse(QRect(50,50,200,100));
painter.setBrush(Qt::blue);
painter.drawPath(myPath);
2、void addPath(const QPainterPath &path)
添加一个路径作为闭合的子路径。
3、void addPolygon(const QPolygonF &polygon)
添加多边形作为非闭合子路径。添加多边形后的当前位置是多边形中的最后一个点。要将线画回到第一点,请使用closeSubpath()函数。
4、void addRect(const QRectF &rectangle)
将给定的矩形作为闭合的子路径添加到此路径。将该矩形作为一组顺时针的线添加。添加矩形后,绘制路径的当前位置在矩形的左上角。
5、void addRegion(const QRegion ®ion)
添加一个区域,区域里可能有多个矩形。QRegion
6、void :addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize)
添加圆角矩形。xRadius和yRadius指定圆角矩形角的椭圆的半径。
当mode为Qt::RelativeSize时,xRadius和yRadius分别以矩形宽度和高度的一半的百分比指定,并且应在0.0到100.0之间。
Qt::SizeMode:指定相对于指定边界矩形的尺寸的矩形角半径模式
- Qt::AbsoluteSize:使用绝对值指定大小。
- Qt::RelativeSize:使用百分比度量。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setBrush(Qt::blue);
QPainterPath path;
path.addRoundedRect(QRect(20,20,200,100),25,25,Qt::AbsoluteSize);
path.addRoundedRect(QRect(20,150,200,100),25,25,Qt::RelativeSize);
painter.drawPath(path);
7、void addText(const QPointF &point, const QFont &font, const QString &text)
添加文本,文本基线的左端位于由参数1指定的点。文本基线见:QFontMetrics
8、void arcMoveTo(const QRectF &rectangle, qreal angle)
这个函数的作用是将弧线的A点移动到参数1矩形的内切椭圆中参数2确定的角度上。如下图的蓝点:
例:
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setBrush(Qt::red);
auto rect = QRect(0,0,200,100);
painter.drawEllipse(rect);
QPainterPath path;
path.arcMoveTo(rect,45);
auto p = path.currentPosition();
painter.setBrush(Qt::cyan);
painter.drawEllipse(p,5,5);
这样设置之后绘制弧线:
path.arcTo(rect,0,90);
painter.drawPath(path);
即:
9、void arcTo(const QRectF &rectangle, qreal startAngle, qreal sweepLength)
创建一个弧形。弧形是椭圆的一部分,参数1是弧形所在椭圆的外接矩形。该弧从指定的startAngle开始,沿逆时针方向延伸sweepLength度。角度以度为单位。 可以使用负角指定顺时针圆弧。添加圆弧后,当前位置是弧形中的最后一个点。要将线画回到第一点,请使用closeSubpath()函数。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
auto rect = QRect(0,50,200,300);
QPainterPath path;
painter.setBrush(Qt::cyan);
painter.setPen(QPen(Qt::red, 5, Qt::DashDotLine));
path.moveTo(rect.center());
path.arcTo(rect,0,90);
painter.drawPath(path);
path.closeSubpath();
10、QRectF boundingRect()
路径的外接矩形。
11、void clear()
清空路径。
12、void closeSubpath()
闭合子路径。通过在子路径的开头绘制一条线来关闭当前子路径,从而自动开始新路径。新路径的当前点是(0,0)。
13、void connectPath(const QPainterPath &path)
通过添加一条从当前路径的最后一个元素到该路径的第一个元素的线,将给定路径连接到该路径。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
auto rect = QRect(0,50,200,300);
QPainterPath path;
painter.setBrush(Qt::cyan);
painter.setPen(QPen(Qt::red, 5, Qt::DashDotLine));
path.moveTo(rect.center());
path.arcTo(rect,0,90);
path.closeSubpath();
QPainterPath path2;
path2.moveTo(rect.bottomRight());
path2.addRect(QRect(rect.bottomRight(),QSize(100,100)));
path.connectPath(path2);
painter.drawPath(path);
14、bool contains(const QPointF &point) const
bool contains(const QRectF &rectangle) const
bool contains(const QPainterPath &p) const
是否包含。。。
15、QRectF controlPointRect()
返回包含此路径中所有点和控制点的矩形。此函数的计算速度明显快于boundingRect()但精度不如boundingRect()。
16、void cubicTo(const QPointF &c1, const QPointF &c2, const QPointF &endPoint)
使用c1和c2指定的控制点在当前位置和给定端点之间添加三次贝塞尔曲线。添加曲线后,当前位置将更新为曲线的终点。贝塞尔曲线 。绘制三次贝塞尔曲线实际涉及到四个点:两个控制点,当前点,结束点。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
QPainterPath path;
painter.setPen(QPen(Qt::red, 5, Qt::DashDotLine));
path.moveTo(20,20);
path.cubicTo(QPointF(100,150),QPointF(230,50),QPointF(300,300));
painter.drawPath(path);
17、QPointF currentPosition()
获取路径当前点。
18、QPainterPath intersected(const QPainterPath &p)
获取路径交集。
19、bool intersects(const QRectF &rectangle) / bool intersects(const QPainterPath &p)
路径是否与路径/矩形相交。
20、qreal length()
返回当前路径的长度。
21、void lineTo(const QPointF &endPoint)
从当前位置到给定端点添加一条直线。绘制直线后,当前位置将更新为直线的终点。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
QPainterPath path;
painter.setPen(QPen(Qt::red, 5, Qt::DashDotLine));
path.lineTo(50,60);
painter.drawPath(path);
22、void moveTo(const QPointF &point)
将当前点移动到给定点,隐式启动新的子路径并关闭上一个子路径。
23、QPointF pointAtPercent(qreal t)
返回当前路径百分比t处的点。参数t必须介于0和1之间。如果路径中存在曲线,则百分比测量与长度不是线性关系。当曲线存在时,百分比参数映射到贝塞尔方程的t参数。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
QPainterPath path;
painter.setPen(QPen(Qt::red, 5, Qt::DashDotLine));
path.lineTo(50,60);
painter.drawPath(path);
painter.setPen(QPen(Qt::cyan, 5, Qt::DashDotLine));
painter.drawEllipse(path.pointAtPercent(0.5),3,3);
path.cubicTo(QPointF(0,0),QPointF(200,200),QPointF(150,20));
painter.drawPath(path);
painter.setPen(QPen(Qt::cyan, 5, Qt::DashDotLine));
painter.drawEllipse(path.pointAtPercent(0.5),3,3);
path.cubicTo(QPointF(0,0),QPointF(200,200),QPointF(150,20));
path.lineTo(350,360);
painter.drawPath(path);
painter.setPen(QPen(Qt::cyan, 5, Qt::DashDotLine));
painter.drawEllipse(path.pointAtPercent(0.3),3,3);
painter.drawEllipse(path.pointAtPercent(0.5),3,3);
painter.drawEllipse(path.pointAtPercent(0.7),3,3);
24、qreal percentAtLength(qreal len)
返回指定长度len处整个路径的百分比。如果路径中存在曲线,则百分比测量与长度不是线性关系。当曲线存在时,百分比参数映射到贝塞尔方程的t参数。
25、void quadTo(const QPointF &c, const QPointF &endPoint)
在当前位置和给定端点之间添加二次贝塞尔曲线,控制点由c指定。添加曲线后,当前点将更新为曲线的终点。绘制二次贝塞尔曲线涉及三个点:当前点、控制点、结束点。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
QPainterPath path;
painter.setPen(QPen(Qt::red, 5, Qt::DashDotLine));
path.moveTo(20,20);
path.quadTo(QPointF(100,150),QPointF(230,50));
painter.drawPath(path);
获取元素个数,见上面的QPainterPath::Element。
27、QPainterPath::Element elementAt(int index)
获取索引的元素类型。见上面的QPainterPath::Element。
元素个数是否为0。见上面的QPainterPath::Element。
29、void setElementPositionAt(int index, qreal x, qreal y)
设置索引的元素位置。
QPainterPath path;
path.lineTo(50,60);
for (auto i = 0;i < path.elementCount();++i)
{
QPainterPath::Element elementType = path.elementAt(i);
qDebug()<<elementType<<elementType.isLineTo()<<elementType.isMoveTo();
}
可见向路径中添加一条直线实际向路径中添加了两个元素:移动到当前点添加了QPainterPath::MoveToElement、添加直线添加了了QPainterPath::LineToElement。
path.setElementPositionAt(0,100,100);
元素0的点从(0,0)修改成(100,100)。效果:
30、void setFillRule(Qt::FillRule fillRule)
设置路径填充规则。填充规则Qt::FillRule
31、QPainterPath simplified()
返回路径的简化版本。将合并所有相交的子路径,并返回不包含相交边的路径。合并连续的平行线。简化路径将始终使用默认的填充规则Qt::OddEvenFill。由于进行贝塞尔曲线相交的数值不确定,贝塞尔曲线可能会展平为线段。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
QPainterPath path;
painter.setPen(QPen(Qt::red, 5, Qt::DashDotLine));
path.moveTo(20,20);
path.quadTo(QPointF(100,150),QPointF(230,50));
path.lineTo(350,360);
painter.drawPath(path);
painter.drawPath(path.simplified());
32、qreal slopeAtPercent(qreal t)
返回路径百分比t处的斜率。参数t必须在0到1之间。如果路径中存在曲线,则百分比测量相对于长度而言也不是线性的。如果存在曲线,则将百分比参数映射到贝塞尔方程的t参数。
33、QPainterPath subtracted(const QPainterPath &p)
返回一个路径减去一个路径的结果(差集)。
34、void swap(QPainterPath &other)
交换两个路径,速度非常快且不会失败。
35、QPolygonF toFillPolygon(const QTransform &matrix)
使用QTransform矩阵将路径转换为多边形。
36、QList<QPolygonF> toFillPolygons(const QTransform &matrix = QTransform())
使用QTransform矩阵将路径转换为多边形列表,并返回该列表。
- 该函数与toFillPolygon()函数的不同之处在于,它创建多个多边形。它的提供是因为绘制几个小多边形通常比绘制一个大多边形要快,即使绘制的点的总数是相同的。
- 该函数与toSubpathPolygons()函数的不同之处在于,它只为具有重叠边界矩形的子路径创建多边形。
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
QPainterPath path;
painter.setPen(QPen(Qt::red, 5, Qt::DashDotLine));
path.moveTo(20,20);
path.quadTo(QPointF(100,150),QPointF(230,50));
path.lineTo(350,360);
path.moveTo(277,33);
path.addEllipse(QRect(277,33,55,55));
painter.drawPath(path);
foreach (auto item, path.toFillPolygons())
{
painter.drawPolygon(item);
}
37、QPainterPath toReversed()
创建并返回路径的反向副本。
反转的是元素的顺序:如果QPainterPath是通过按指定顺序调用moveTo()、lineTo()和cubicTo()函数组成的,则反转的副本是通过调用cubicTo()、lineTo()和moveTo()组成的。
38、QList<QPolygonF> toSubpathPolygons(const QTransform &matrix = QTransform())
使用QTransform矩阵将路径转换为多边形列表。此函数为每个子路径创建一个多边形,而不考虑相交的子路径(即重叠的边界矩形)。要确保正确填充这些重叠的子路径,请改用toFillPolygons()函数。
例,上面36的例子:
foreach (auto item, path.toSubpathPolygons())
{
painter.drawPolygon(item);
}
39、void translate(const QPointF &offset)
按给定偏移量转换路径中的所有元素。
40、QPainterPath translated(const QPointF &offset)
返回按给定偏移量转换的路径副本。
41、QPainterPath united(const QPainterPath &p)
返回与参数路径的并集。
五、重载运算符
QPainterPath支持的运算符操作:
1、!=和==:判断两路径是否相同。
2、&:获取两路径的交集。
3、+:获取两路径的并集。
4、-:获取两路径的差集。
5、|:获取两路径的并集,与“+”一样。