接下来实现平滑曲线的效果。
1. 绘制原理
绘制平滑曲线用到QPainterPath::cubicTo()函数,该函数用来在当前点和结束点之间绘制贝瑟尔曲线,函数原型如下:
void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF &endPoint);
void QPainterPath::cubicTo(qreal c1X, qreal c1Y, qreal c2X, qreal c2Y, qreal endPointX, qreal endPointY);
只要计算出c1和c2两个控制点的坐标,就可以在sp起始点和ep结束点之间绘制一条平滑曲线,计算方法如下:
以上,我是通过在亿图图示绘图工具里使用贝塞尔曲线工具,绘制的一条平滑曲线。
关于贝瑟尔曲线的动态演示,可以查看这里:http://yisibl.github.io/cubic-bezier
2. 代码实现
首先,在widget.cpp中实现一个createSmoothPath()函数,如下:
QPainterPath createSmoothPath(const QVector<QPoint> &points)
{
int count = points.count();
if (count == 0) {
return QPainterPath();
}
QPainterPath path;
path.moveTo(points.at(0));
for (int i = 0; i < count - 1; ++i) {
// 控制点的 x 坐标为 sp 与 ep 的 x 坐标和的一半
// 第一个控制点 c1 的 y 坐标为起始点 sp 的 y 坐标
// 第二个控制点 c2 的 y 坐标为结束点 ep 的 y 坐标
QPoint sp = points.at(i);
QPoint ep = points.at(i + 1);
QPoint c1 = QPoint((sp.x() + ep.x()) / 2, sp.y());
QPoint c2 = QPoint((sp.x() + ep.x()) / 2, ep.y());
path.cubicTo(c1, c2, ep);
}
return path;
}
然后,修改函数,如下:
void Widget::drawTempLine(bool high)
{
// ...
QVector<QPoint> points;
for (int i = 0; i < 7; i++) {
points.append(QPoint(pointX[i], pointY[i]));
}
// 3. 开始绘制
// ...
// 3.3 绘制曲线
#if 0
// 折线
for (int i = 0; i < 6; i++) {
pen.setStyle(i == 0 ? Qt::DotLine : Qt::SolidLine); // 虚线
painter.setPen(pen);
painter.drawLine(pointX[i], pointY[i], pointX[i + 1], pointY[i + 1]);
}
#else
// 平滑曲线
QBrush brush = painter.brush();
brush.setStyle(Qt::NoBrush);
painter.setBrush(brush);
QPainterPath path = createSmoothPath(points);
painter.drawPath(path);
#endif
}





