QT利用QPainter实现自定义圆弧进度条组件

           在可视化应用中,弧形进度条应用也比较广泛,本文示例封装了一个可复用、个性化的弧形进度条组件。本文示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。主要结构就是外围一圈圆角进度,中间加上标题和对应进度的百分比,进度条的起始角度和结束角度可以自行调整,这样的话进度条的开口就可以在左边右边上边下边等任意位置,通过调整角度就能实现。

一、简述

         本文为大家分享了QT利用QPainter实现自定义圆弧进度条组件的具体代码。绘制的核心就是drawArc函数。

二、 设计思路   

        主要思路:基类选择“QWidget”,使用QPainter根据图形需求画圆和圆弧,根据具体的value值旋转坐标系,达到旋转效果,旋转度数是根据value值,占比求得。最中间需要画文字上去,每次更新value时调用update()方法,重绘界面。

        实现功能:

  • 可设置范围
  • 可设置开始旋转角度、结束旋转角度
  • 可设置过度动画时常
  • 可设置仪表盘标题
  • 可设置背景、进度条、值、标题颜色
  • 自适应窗体拉伸,文字自动缩放
三、效果 

 

四、核心代码  
1、头文件
#ifndef PROGRESSARC_H
#define PROGRESSARC_H

#include <QWidget>

struct ProgressArcPrivate;
class ProgressArc : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(double value READ value WRITE setValue CONSTANT)
    Q_PROPERTY(QString title READ title WRITE setTitle CONSTANT)
    Q_PROPERTY(bool percent READ percent WRITE setPercent CONSTANT)
    Q_PROPERTY(double min READ min WRITE setMin CONSTANT)
    Q_PROPERTY(double max READ max WRITE setmax CONSTANT)
    Q_PROPERTY(double startAngle READ startAngle WRITE setStartAngle CONSTANT)
    Q_PROPERTY(double endAngle READ endAngle WRITE setEndAngle CONSTANT)
    Q_PROPERTY(QColor arcColor READ arcColor WRITE setArcColor CONSTANT)
    Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor CONSTANT)
    Q_PROPERTY(QColor titleColor READ titleColor WRITE setTitleColor CONSTANT)
    Q_PROPERTY(QColor baseColor READ baseColor WRITE setBaseColor CONSTANT)
    Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor CONSTANT)
public:
    explicit ProgressArc(const QString &title, QWidget *parent = nullptr);
    ~ProgressArc();

    QSize sizeHint() const override;
    QSize minimumSizeHint() const override;

    double value() const;
    void setValue(const double value);

    void setTitle(const QString &title);
    QString title() const;

    void setPercent(const bool percent);
    bool percent() const;

    void setMin(const double min);
    double min() const;

    void setmax(const double max);
    double max() const;

    void setStartAngle(const double startAngle);
    double startAngle() const;

    void setEndAngle(const double endAngle);
    double endAngle() const;

    void setArcColor(const QColor &color);
    QColor arcColor() const;

    void setTextColor(const QColor &color);
    QColor textColor() const;

    void setTitleColor(const QColor &color);
    QColor titleColor() const;

    void setBaseColor(const QColor &color);
    QColor baseColor() const;

    void setBackgroundColor(const QColor &color);
    QColor backgroundColor() const;

signals:
    void valueChanged(const double value);

private slots:
    void onStartAnimation(const double value);

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    void drawArc(QPainter *painter);
    void drawText(QPainter *painter);

    QScopedPointer<ProgressArcPrivate> d;
};

#endif // PROGRESSARC_H
2、实现代码
#include "progressarc.h"

#include <QPainter>
#include <QPropertyAnimation>

struct ProgressArcPrivate{
    double minValue = 0;
    double maxValue = 100;
    double value = 0;
    double startAngle = -90;
    double endAngle = 270;

    QColor arcColor = QColor(QLatin1String("#4da1ff"));
    QColor textColor = QColor(QLatin1String("#4da1ff"));
    QColor titleColor = QColor(80, 80, 80);
    QColor baseColor = QColor(179,179,179);
    QColor backgroundColor = Qt::transparent;

    bool percent = true;
    QString title;

    QPropertyAnimation *animation;
};

ProgressArc::ProgressArc(const QString &title, QWidget *parent)
    : QWidget(parent)
    , d(new ProgressArcPrivate)
{
    setTitle(title);
    d->animation = new QPropertyAnimation(this, "value", this);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    connect(this, &ProgressArc::valueChanged, this, &ProgressArc::onStartAnimation);
}

ProgressArc::~ProgressArc()
{
}

void ProgressArc::setTitle(const QString &title)
{
    d->title = title;
    update();
}

QString ProgressArc::title() const
{
    return d->title;
}

void ProgressArc::setPercent(const bool percent)
{
    d->percent = percent;
    update();
}

bool ProgressArc::percent() const
{
    return d->percent;
}

void ProgressArc::setMin(const double min)
{
    d->minValue = min;
    update();
}

double ProgressArc::min() const
{
    return d->minValue;
}

void ProgressArc::setmax(const double max)
{
    d->maxValue = max;
    update();
}

double ProgressArc::max() const
{
    return d->maxValue;
}

void ProgressArc::setStartAngle(const double startAngle)
{
    d->startAngle = startAngle;
    update();
}

double ProgressArc::startAngle() const
{
    return d->startAngle;
}

void ProgressArc::setEndAngle(const double endAngle)
{
    d->endAngle = endAngle;
    update();
}

double ProgressArc::endAngle() const
{
    return d->endAngle;
}

void ProgressArc::setArcColor(const QColor &color)
{
    d->arcColor = color;
    update();
}

QColor ProgressArc::arcColor() const
{
    return d->arcColor;
}

void ProgressArc::setTextColor(const QColor &color)
{
    d->textColor = color;
    update();
}

QColor ProgressArc::textColor() const
{
    return d->textColor;
}

void ProgressArc::setTitleColor(const QColor &color)
{
    d->titleColor = color;
    update();
}

QColor ProgressArc::titleColor() const
{
    return d->titleColor;
}

void ProgressArc::setBaseColor(const QColor &color)
{
    d->baseColor = color;
    update();
}

QColor ProgressArc::baseColor() const
{
    return d->baseColor;
}

void ProgressArc::setBackgroundColor(const QColor &color)
{
    d->backgroundColor = color;
    update();
}

QColor ProgressArc::backgroundColor() const
{
    return d->backgroundColor;
}

QSize ProgressArc::sizeHint() const
{
    return QSize(200, 200);
}

QSize ProgressArc::minimumSizeHint() const
{
    return QSize(80, 80);
}

void ProgressArc::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    // 背景
    if (d->backgroundColor != Qt::transparent) {
        painter.setPen(Qt::NoPen);
        painter.fillRect(rect(), d->backgroundColor);
    }

    // 平移中心
    painter.translate(width() / 2, height() / 2);

    // 圆弧
    drawArc(&painter);

    // text
    drawText(&painter);
}

void ProgressArc::onStartAnimation(const double value)
{
    if(value < d->minValue
        || value > d->maxValue
        || value == d->value)
        return;

    int start = d->value;
    int end = value;

    d->animation->setStartValue(start);
    d->animation->setEndValue(end);
    d->animation->start();
}

double ProgressArc::value() const
{
    return d->value;
}

void ProgressArc::setValue(const double value)
{
    d->value = value;
    update();
}

void ProgressArc::drawArc(QPainter *painter)
{
    double min = qMin(width(), height());
    double arcWidth = min / 10.0;
    double radius = min / 2.0 - arcWidth - 5;
    QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
    QPen pen;
    pen.setWidthF(arcWidth);
    pen.setCapStyle(Qt::RoundCap);

    // 圆弧背景
    double angle = d->endAngle - d->startAngle;
    pen.setColor(d->baseColor);
    painter->setPen(pen);
    painter->drawArc(rect, d->startAngle * 16, angle * 16);

    // 圆弧进度
    double spanAngle = angle * ((d->value - d->minValue) / (d->maxValue - d->minValue));
    double startAngle = d->endAngle - spanAngle;
    pen.setColor(d->arcColor);
    painter->setPen(pen);
    painter->drawArc(rect, startAngle * 16, spanAngle * 16);
}

void ProgressArc::drawText(QPainter *painter)
{
    double min = qMin(width(), height());
    double arcWidth = min / 10.0;
    double radius = min / 2.0 - arcWidth - 5;
    painter->setPen(d->textColor);

    QFont font("Microsoft YaHei", radius / 4.0);
    painter->setFont(font);

    QString strValue;
    if (d->percent) {
        double temp = d->value / (d->maxValue - d->minValue) * 100;
        strValue = QString("%1%").arg(temp, 0, 'f', 2);
    } else
        strValue = QString("%1").arg(d->value, 0, 'f', 2);

    // value
    QRectF valueRect(-radius, 0, radius * 2, radius / 3);
    painter->drawText(valueRect, Qt::AlignCenter, strValue);

    painter->setPen(d->titleColor);
    font.setPixelSize(radius / 4.0);
    painter->setFont(font);

    // title
    QRectF textRect(-radius, -radius / 2.5, radius * 2, radius / 3);
    painter->drawText(textRect, Qt::AlignCenter, d->title);
}

以上是圆弧进度条组件实现代码,在实际使用中,可以根据需要自定义动画文件和样式。

该自定义控件主要特点有:

1、纯QPaint绘制,不包括图片等文件;

2、多种自定义控制,非常灵活;

3、能够自适应大小,不需要手动调整;

4、支持动画效果。

        需要注意的是,在使用QPainter实现自定义圆弧进度条组件时,需要灵活运用QPainter的绘图函数和提供给用户的交互函数,并注意处理用户的交互操作和组件的尺寸调整等问题。

五、使用示例

以下是一个简单的示例代码,演示了如何在Qt中使用此控件:

#include "mainwindow.h"
#include "progressarc.h"

#include <QtWidgets>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QSlider *slider = new QSlider(this);
    slider->setRange(0, 100);

    ProgressArc *progressArc1 = new ProgressArc(tr("赞成"), this);
    connect(slider, &QSlider::valueChanged, progressArc1, &ProgressArc::valueChanged);

    ProgressArc *progressArc2 = new ProgressArc(tr("反对"), this);
    progressArc2->setArcColor(QColor(250, 118, 113));
    progressArc2->setStartAngle(-50);
    progressArc2->setEndAngle(230);
    connect(slider, &QSlider::valueChanged, progressArc2, &ProgressArc::valueChanged);

    ProgressArc *progressArc3 = new ProgressArc(tr("弃权"), this);
    progressArc3->setArcColor(QColor(41, 197, 90));
    progressArc3->setStartAngle(-140);
    progressArc3->setEndAngle(140);
    connect(slider, &QSlider::valueChanged, progressArc3, &ProgressArc::valueChanged);

    QWidget *widget = new QWidget(this);
    QHBoxLayout *layout = new QHBoxLayout(widget);
    layout->addWidget(progressArc1);
    layout->addWidget(progressArc2);
    layout->addWidget(progressArc3);
    layout->addWidget(slider);
    setCentralWidget(widget);
    resize(670, 260);
}

MainWindow::~MainWindow()
{
}

总结一下,圆弧进度条组件的设计方法和流程如下:

  1. 定义组件的功能和需求:确定组件需要实现的功能,例如显示进度、设置颜色等。

  2. 设计组件的外观:确定圆弧的样式,包括颜色、宽度、起始角度等。

  3. 创建组件的类:根据需求,创建一个新的类来实现组件的功能。

  4. 实现组件的逻辑:在组件的类中,编写代码来处理用户的输入和显示组件的状态。

  5. 测试组件的功能:使用测试数据来验证组件是否正常工作,并修复可能存在的问题。

        谢谢您的关注和阅读!如有任何问题或需要帮助,请随时与我联系。希望您能继续支持并享受更多精彩的内容。祝您生活愉快!

六、源代码下载

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我将根据您的要求为您提供有关自定义Qt进度条代码的详细回答。 在Qt中,您可以自定义进度条的外观和行为。以下是一些代码示例,演示如何创建自定义Qt进度条。 1. 创建自定义进度条类 在Qt中,您可以通过创建自定义进度条类来实现自定义进度条。以下是创建自定义进度条类的示例代码: ```cpp class MyProgressBar : public QProgressBar { public: MyProgressBar(QWidget *parent = 0); protected: virtual void paintEvent(QPaintEvent *event); }; ``` 在这个示例中,我们创建了一个名为 MyProgressBar 的类,它继承自 Qt 的 QProgressBar 类。我们重写了 paintEvent 函数,以便重绘进度条的外观。 2. 重写 paintEvent 函数 以下是一个示例代码,演示如何在自定义进度条中重写 paintEvent 函数: ```cpp void MyProgressBar::paintEvent(QPaintEvent *event) { QProgressBar::paintEvent(event); QPainter painter(this); QRect rect = QRect(0, 0, width(), height()); painter.fillRect(rect, Qt::gray); painter.fillRect(rect.adjusted(1, 1, -1, -1), Qt::white); painter.fillRect(rect.adjusted(1, 1, -1, -1), Qt::blue); } ``` 在这个示例中,我们首先调用 QProgressBar 类的 paintEvent 函数。然后,我们创建一个 QPainter 对象,并使用它绘制进度条。我们首先绘制灰色背景,然后绘制白色边框,最后绘制蓝色进度条。 3. 使用自定义进度条 在您创建了自定义进度条类之后,您可以将其用作常规进度条。以下是一个示例代码,演示如何在 Qt 中使用自定义进度条类: ```cpp MyProgressBar *myProgressBar = new MyProgressBar(this); myProgressBar->setRange(0, 100); myProgressBar->setValue(50); ``` 在这个示例中,我们首先创建了一个 MyProgressBar 类的实例,然后设置了进度条的范围和当前值。 总结 以上是关于如何在 Qt 中创建自定义进度条的示例代码。您可以根据您的需求修改这些示例代码,以便创建出符合您想要的外观和行为的自定义进度条

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值