欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

绘制渐变的贝塞尔曲线

程序员文章站 2023-12-27 09:06:03
...

前面介绍了使用Qt中的API绘制贝塞尔曲线,使用Qt的API绘制贝塞尔曲线可参见绘制贝塞尔曲线,本章介绍一下使用线段连接的方式绘制一条渐变的贝塞尔曲线。效果如下图所示:
绘制渐变的贝塞尔曲线

二阶贝塞尔曲线的公式如下:
B(t)=P0(1t)3+3P1t(1t)2+3P2t2(1t)+P3t3,t[0,1]

P0为起始点的坐标,P3为终点的坐标,P1P2为控制点的坐标。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;
}

上一篇:

下一篇: