前言
本篇文章我们讲解QT实现圆形进度条,并实现动态的效果。
一、编程思路
实现QT圆形进度条其实是非常简单的,思路就是画两个圆弧。
这里大家就会觉得很奇怪了为什么画两个圆弧就能实现圆形进度条了呢?那么下面我们一个个圆弧来画看看效果。
代码:
painter.translate(width() / 2, height() / 2); QPen pen; pen.setWidth(20);//设置笔的大小 /*设置圆弧连接处为圆形*/ pen.setJoinStyle(Qt::RoundJoin); pen.setCapStyle(Qt::RoundCap); pen.setColor(Qt::gray); painter.setPen(pen); QRect rect(-(height() / 4), -(height() / 4), (height() / 2), (height() / 2)); painter.drawArc(rect, 0, 360 * 16);/*外部圆弧*/
效果:
我们首先画一个0到360°角的圆弧,并且把笔的颜色设置为灰色,这样的效果看起来就是空心的一个圆环了。这里需要特别注意的就是需要设置一下笔的大小,因为默认笔的大小画出来的圆弧是一根线,这里需要将笔的大小设置的大一点这样看起来才像是一个空心的圆环。
现在我们来画这个进度条,进度条其实也是画圆弧来实现的,这里根据进度条的百分比来设置进度条的颜色。这个进度条绘制的方法和上面的绘制方法是一样的,上面的圆弧的角度是0到360这样看起来就是一个圆形,那么这里我们绘制这个进度条的时候根据需求来绘制角度就可以了。
通过改变绘制角度来达到进度条的效果。
/*进度条颜色设置(根据百分比设置成不同的颜色)*/ void Widget::ProgressBarColorSet(QPainter& painter) { QPen pen; pen.setWidth(20); pen.setJoinStyle(Qt::RoundJoin); pen.setCapStyle(Qt::RoundCap); Light_Intensity = (float)m_endAngle / 360 * 100; if(Light_Intensity <= 25) { pen.setColor(Qt::green); } else if(Light_Intensity > 25 && Light_Intensity <= 50) { pen.setColor(Qt::blue); } else if(Light_Intensity > 50 && Light_Intensity <= 75) { pen.setColor(Qt::yellow); } else { pen.setColor(Qt::red); } painter.setPen(pen); } painter.drawArc(rect, m_startAngle * 16, -m_endAngle * 16);/*内部进度条*/
二、核心代码实现
代码部分主要就是来讲解一下动画的实现,QT中的动画类我们在前面的文章中也讲解到了大家可以去看之前的文章。
主要就是将角度设置为一个属性提供给QPropertyAnimation创建出的对象类修改以达到动画的效果。
修改自定义的endAngle属性来达到修改圆形进度条的进度的效果,并且使用update()函数更新效果。
widget.c
#include "widget.h" #include <QPainter> #include <QFont> #include <QProgressBar> #include <QRect> #include <QPalette> #include <QPushButton> Widget::Widget(QWidget *parent): QWidget(parent), Light_Intensity(0), m_startAngle(90), m_endAngle(0) { /*背景图设置*/ QPixmap pixmap(":/backgruond.gif"); QPalette palette; palette.setBrush(backgroundRole(), QBrush(pixmap)); setPalette(palette); setAutoFillBackground(true); QPushButton* button = new QPushButton(this); button->setText("点我"); connect(button, SIGNAL(clicked()), this, SLOT(clicked())); animation = new QPropertyAnimation(this, "endAngle"); animation->setDuration(500); animation->setStartValue(0); // 属性的起始值 setFixedSize(1024, 600); } void Widget::clicked() { animation->setStartValue(m_endAngle); // 属性的起始值 animation->setEndValue(m_endAngle + 36); // 属性的结束值 setEndAngle(m_endAngle + 36); // 启动动画 animation->start(); } void Widget::DrawText(QPainter& painter) { painter.save(); painter.translate(width() / 2, height() / 2); QRect rect2(-(height() / 6), -(height() / 6), (height() / 3), (height() / 3)); QRect rect1(-(height() / 6), -(height() / 6), (height() / 3), (height() / 6)); QPen pen; pen.setColor(Qt::white); painter.setPen(pen); QFont font1("微软雅黑", 25); painter.setFont(font1); painter.drawText(rect1, Qt::AlignCenter, "光照强度"); QFont font2("微软雅黑", 30); painter.setFont(font2); painter.drawText(rect2, Qt::AlignCenter, QString::number(Light_Intensity, 'g', 3) + "%"); painter.restore(); } /*进度条颜色设置(根据百分比设置成不同的颜色)*/ void Widget::ProgressBarColorSet(QPainter& painter) { QPen pen; pen.setWidth(20); pen.setJoinStyle(Qt::RoundJoin); pen.setCapStyle(Qt::RoundCap); Light_Intensity = (float)m_endAngle / 360 * 100; if(Light_Intensity <= 25) { pen.setColor(Qt::green); } else if(Light_Intensity > 25 && Light_Intensity <= 50) { pen.setColor(Qt::blue); } else if(Light_Intensity > 50 && Light_Intensity <= 75) { pen.setColor(Qt::yellow); } else { pen.setColor(Qt::red); } painter.setPen(pen); } void Widget::DrawCirque(QPainter& painter) { painter.save(); painter.translate(width() / 2, height() / 2); QPen pen; pen.setWidth(20);//设置笔的大小 /*设置圆弧连接处为圆形*/ pen.setJoinStyle(Qt::RoundJoin); pen.setCapStyle(Qt::RoundCap); pen.setColor(Qt::gray); painter.setPen(pen); QRect rect(-(height() / 4), -(height() / 4), (height() / 2), (height() / 2)); painter.drawArc(rect, 0, 360 * 16);/*外部圆弧*/ ProgressBarColorSet(painter);//设置进度条颜色 painter.drawArc(rect, m_startAngle * 16, -m_endAngle * 16);/*内部进度条*/ painter.restore(); } void Widget::paintEvent(QPaintEvent* event) { Q_UNUSED(event); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true);//设置抗锯齿 DrawCirque(painter);//绘制圆环进度条 DrawText(painter);//绘制文字 } float Widget::GetLight_Intensity() { return Light_Intensity; } Widget::~Widget() { }
Q_PROPERTY 是 Qt 中的一个宏,能够帮助开发人员将类的成员变量(或方法)暴露为一个属性( property )。这使得其他开发人员可以通过使用该类的对象来读取或设置这些属性。这些属性可用于界面设计、特定功能或其他目的。
Q_PROPERTY 宏需要几个参数来定义一个属性,包括:属性的返回类型、读取函数、写入函数。
对于 Q_PROPERTY(int endAngle READ endAngle WRITE setEndAngle NOTIFY endAngleChanged) ,它定义了一个名为 endAngle 的整数属性。其他开发人员可以使用 readEndAngle() 和 writeEndAngle() 方法来分别读取和设置此属性,并且 endAngleChanged() 信号将在属性更改时发出通知。此属性是可读取、可写入的并且是整数类型。
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QPaintEvent> #include <QPen> #include <QPropertyAnimation> #include <QDebug> class Widget : public QWidget { Q_OBJECT /*定义一个可读(READ)并且可写(WRITE)的属性,并且可以通过属性名称进行访问*/ Q_PROPERTY(int endAngle READ endAngle WRITE setEndAngle NOTIFY endAngleChanged) float Light_Intensity;//光照强度 int m_startAngle; int m_endAngle; QPropertyAnimation* animation; void DrawCirque(QPainter& painter); void DrawText(QPainter& painter); void ProgressBarColorSet(QPainter& painter); public: Widget(QWidget *parent = nullptr); ~Widget(); float GetLight_Intensity();//获取光照强度 int endAngle() const { return m_endAngle; } void setEndAngle(const int& endAngle) { m_endAngle = endAngle; update(); } protected: void paintEvent(QPaintEvent* event); signals: void endAngleChanged(int Angle); protected slots: void clicked(); }; #endif // WIDGET_H
总结
掌握好QPainter的实现我们可以做出非常多的好看的项目,希望大家好好的学习QPainter的绘制方法。现在我们的QT桌面项目又更近了一步,大家继续加油!我也会持续为大家写出更多的项目。