How to draw a linear gradient arc with Qt QPainter?

我们两清 提交于 2019-12-01 04:02:22

I know this is an old question but I came across it some days ago and I think I have a solution. What you want is to create a conical gradient and clip the disk you want to use as circular loading bar. Here is an example:

widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class QPaintEvent;

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    void setLoadingAngle(int loadingAngle);
    int loadingAngle() const;

    void setDiscWidth(int width);
    int discWidth() const;

protected:
    void paintEvent(QPaintEvent *);

private:
    int m_loadingAngle;
    int m_width;
};

#endif // WIDGET_H

widget.cpp:

#include "widget.h"

#include <QPaintEvent>
#include <QPainter>
#include <QConicalGradient>
#include <QPen>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    m_loadingAngle(0),
    m_width(0)
{
}

Widget::~Widget()
{
}

void Widget::setLoadingAngle(int loadingAngle)
{
    m_loadingAngle = loadingAngle;
}

int Widget::loadingAngle() const
{
    return m_loadingAngle;
}

void Widget::setDiscWidth(int width)
{
    m_width = width;
}

int Widget::discWidth() const
{
    return m_width;
}

void Widget::paintEvent(QPaintEvent *)
{
    QRect drawingRect;
    drawingRect.setX(rect().x() + m_width);
    drawingRect.setY(rect().y() + m_width);
    drawingRect.setWidth(rect().width() - m_width * 2);
    drawingRect.setHeight(rect().height() - m_width * 2);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    QConicalGradient gradient;
    gradient.setCenter(drawingRect.center());
    gradient.setAngle(90);
    gradient.setColorAt(0, QColor(178, 255, 246));
    gradient.setColorAt(1, QColor(5, 44, 50));

    int arcLengthApproximation = m_width + m_width / 3;
    QPen pen(QBrush(gradient), m_width);
    pen.setCapStyle(Qt::RoundCap);
    painter.setPen(pen);
    painter.drawArc(drawingRect, 90 * 16 - arcLengthApproximation, -m_loadingAngle * 16);
}

main.cpp:

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Widget w;
    w.setDiscWidth(20);
    w.setLoadingAngle(270);
    w.show();

    return a.exec();
}

And the result is:

Of course, it is not the complete and exact solution but I think it is everything you need to know in order to achieve what you want. The rest are details not hard to implement.

This solution is not exactly what you're after; the gradient goes from top to bottom, rather than around the circle:

#include <QtWidgets>

class Widget : public QWidget
{
public:
    Widget() {
        resize(200, 200);
    }

    void paintEvent(QPaintEvent *) {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);

        const QRectF bounds(0, 0, width(), height());
        painter.fillRect(bounds, "#1c1c1c");

        QPen pen;
        pen.setCapStyle(Qt::RoundCap);
        pen.setWidth(20);

        QLinearGradient gradient;
        gradient.setStart(bounds.width() / 2, 0);
        gradient.setFinalStop(bounds.width() / 2, bounds.height());
        gradient.setColorAt(0, "#1c1c1c");
        gradient.setColorAt(1, "#28ecd6");

        QBrush brush(gradient);
        pen.setBrush(brush);
        painter.setPen(pen);

        QRectF rect = QRectF(pen.widthF() / 2.0, pen.widthF() / 2.0, width() - pen.widthF(), height() - pen.widthF());
        painter.drawArc(rect, 90 * 16, 0.65 * -360 * 16);
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    Widget w;
    w.show();

    return app.exec();
}

However, it is an arc with a linear gradient! :p

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!