绘制渐变的贝塞尔曲线
程序员文章站
2023-12-27 09:06:03
...
前面介绍了使用Qt中的API绘制贝塞尔曲线,使用Qt的API绘制贝塞尔曲线可参见绘制贝塞尔曲线,本章介绍一下使用线段连接的方式绘制一条渐变的贝塞尔曲线。效果如下图所示:
二阶贝塞尔曲线的公式如下:
为起始点的坐标,为终点的坐标,和为控制点的坐标。t在0-1之间取值,B(t)为计算的曲线坐标点。
完整的程序代码如下,本例子中取100个样点进行绘制:
头文件
#include <QWidget>
class BezierCurve : public QWidget
{
Q_OBJECT
public:
BezierCurve(QWidget *parent = nullptr);
~BezierCurve();
protected:
void paintEvent(QPaintEvent *event) override;
private:
int m_SampleCount;
// 绘制贝塞尔曲线
void drawBezierCurve(QPainter* painter, QPointF startPos, QPointF c1, QPointF c2, QPointF endPos);
// 获取渐变的颜色
QColor getGradientColor(int index);
QColor m_StartColor; // 起始颜色
QColor m_EndColor; // 结束颜色
};
源文件
#include "BezierCurve.h"
#include <QPainter>
#include <QVBoxLayout>
#include <QColor>
#include <QApplication>
#include <QStyleOption>
BezierCurve::BezierCurve(QWidget *parent)
:QWidget(parent)
{
m_SampleCount = 100;
m_StartColor = QColor(255, 255, 0);
m_EndColor = QColor(0, 255, 255);
this->setProperty("NormalWidget", "NormalWidget");
}
BezierCurve::~BezierCurve()
{
}
void BezierCurve::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// 绘制样式
QStyleOption opt;
opt.init(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
painter.setRenderHint(QPainter::Antialiasing, true);
// 绘制贝塞尔曲线
drawBezierCurve(&painter, QPointF(20, 20), QPointF(20, 500), QPointF(500, 20), QPointF(500, 500));
return QWidget::paintEvent(event);
}
void BezierCurve::drawBezierCurve(QPainter* painter, QPointF startPos, QPointF c1, QPointF c2, QPointF endPos)
{
painter->save();
QPointF tempPos = startPos;
for (int i=0; i<=m_SampleCount; ++i)
{
// 设置画笔
QPen pen;
QColor lineColor = getGradientColor(i);
pen.setColor(lineColor);
pen.setWidth(3);
painter->setPen(pen);
qreal t = i * 1.0 / m_SampleCount;
QPointF pos = pow((1 - t), 3) * startPos + \
3 * t * pow((1 - t), 2) * c1 + \
3 * t * t * (1 - t) * c2 + \
pow(t, 3) * endPos;
// 绘制贝塞尔曲线
painter->drawLine(tempPos, pos);
tempPos = pos;
}
painter->restore();
}
QColor BezierCurve::getGradientColor(int index)
{
qreal redInterval = (m_EndColor.red() - m_StartColor.red()) * 1.0 / m_SampleCount;
qreal greenInterval = (m_EndColor.green() - m_StartColor.green()) * 1.0 / m_SampleCount;
qreal blueInterval = (m_EndColor.blue() - m_StartColor.blue()) * 1.0 / m_SampleCount;
QColor gradientColor;
gradientColor.setRed(redInterval * index + m_StartColor.red());
gradientColor.setGreen(greenInterval * index + m_StartColor.green());
gradientColor.setBlue(blueInterval * index + m_StartColor.blue());
return gradientColor;
}