首页 > 其他分享 >QT利用QPainter实现自定义圆弧进度条组件

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

时间:2024-07-18 12:56:15浏览次数:18  
标签:QColor ProgressArc QT 自定义 进度条 double void value const

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

一、简述

         本文为大家分享了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. 测试组件的功能:使用测试数据来验证组件是否正常工作,并修复可能存在的问题。

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

六、源代码下载

标签:QColor,ProgressArc,QT,自定义,进度条,double,void,value,const
From: https://blog.csdn.net/u012959478/article/details/140443834

相关文章

  • 【Qt】探索Qt框架:开发经典贪吃蛇游戏的全过程与实践
    文章目录引言项目链接:1.Qt框架的使用简介2.贪吃蛇游戏设计2.1游戏规则和玩法介绍2.2游戏界面设计概述3.核心代码解析3.1主界面(GameHall)3.1.1布局和功能介绍3.1.2代码实现分析3.2游戏选择界面(GameSelect)3.2.1功能介绍3.2.2代码实现分析3.3游戏房间(GameRoom......
  • 2024-07-18 给vue项目添加自定义路由守卫
    要配置路由守卫要使用到vue-router,它是Vue.js官方的路由管理器,主要用于帮助开发者构建单页面应用(SinglePageApplication,简称SPA)。步骤一:新建路由文件,文件名随意,建议叫router.ts,规范一点//router.tsimport{createRouter,createWebHashHistory}from"vue-router";i......
  • 使用Spring Boot AOP和自定义注解优雅实现操作日志记录
    使用SpringBootAOP和自定义注解优雅实现操作日志记录大家好,今天我们来聊聊如何在SpringBoot项目中,通过AOP(面向切面编程)和自定义注解,优雅地实现操作日志记录。操作日志对于系统的可维护性和安全性至关重要,它能帮助我们追踪用户行为,排查问题。什么是AOP?AOP,全称Aspect-Oriented......
  • 自定义转换器
    我们要自定义转换器就要声明一个类,然后继承父类的BaseConverter需要用正则表达式的需要重写父类的regex代码实现: fromflaskimportFlaskfromwerkzeug.routingimportBaseConverterapp=Flask(__name__)classCustomConverter(BaseConverter):#自定义转换器要继承......
  • 【QT开发】串口通信管理QSerialPort类详解及实战应用
    QSerialPort是Qt提供的一个功能强大、简单易用的串口通信类。通过本文的学习,您应该对QSerialPort的基本使用、高级应用技巧及相关注意事项有了全面的理解。在实际项目中,QSerialPort可以帮助实现与外部设备的串口通信,确保数据的可靠传输和接收。希望本文能帮助您更好地......
  • QTimer的一个莫名错误
    该错误很莫名奇妙,暂时也不知道为什么会出错。是这样的,我自定义了一个QThread,在run函数中会循环打开一个资源,这个资源会出现打不开的情况,所以如果打开失败,就需要等待一段时间再次去打开。因为中间有可能手动终端等待,手动触发再次尝试打开资源,所以没有直接使用msleep,搞的比较复杂。......
  • Qt处理中文编码出现错误
    Qt的QString使用起来非常方便,内部封装了很多很好用的函数和功能。其中有个函数是simplified(),这个函数可以除去字符串的首尾和内部的空白(空白包括\t,\n,\v,\f,\r,'')。其中Qt帮助文档中说的是移除的ASCII中的\t,\n,\v,\f,\r,''。这里隐藏着一个坑。如果字符串不是完全的ASCII字符......
  • Netcode for Entities如何添加自定义序列化,让GhostField支持任意类型?以int3为例(1.2.3
    一句话省流:很麻烦也很抽象,能用内置支持的类型就尽量用。首先看文档。官方文档里一开头就列出了所有内置的支持的类型:GhostTypeTemplates其中Entity类型需要特别注意一下:在同步这个类型的时候,如果是刚刚Instantiate的Ghost(也就是GhostId尚未生效,上一篇文章里说过这个问题),那么客......
  • Qt - QtWebEngineWidgets模块
    1、QtWebEngineWidgets模块 #include<QtWebEngineWidgets>QT+=webenginewidgets 1.1QWebEnginePage示例代码:#include<QtWebEngineWidgets>#include<QWebEnginePage>//1、创建一个新的QWebEnginePage实例:page=newQWebEnginePage(this);......
  • mqtt mosquitto开源库实现
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、MQTT是什么?二、使用步骤1.服务器配置安装并开启mosquitto2.客户端代码总结前言提示:这里可以添加本文要记录的大概内容:mosquitto开源库实现简单的mqtt发布和订阅功能程序。提示:......