Qt自绘制之进度条

众所周知,Qt自带了一些进度条控件,但有时并不能满足我们日常的使用要求,所以有时我们需要自己自绘制一些进度条来使界面变得好看。我在这个程序中绘制了如下3种进度条:

 

 

 这个3种进度条各有特色,能适应不同的场景需要。接下来我将一步步讲解。

首先老规矩,将.h和.cpp的文件贴出来,我用的qt版本是5.9.9,如果是低版本的要注意下QWidget的位置。代码如下:

#pragma once

//.h文件
#include <QtWidgets/QWidget>
#include "ui_CustomProgress.h"

#include <QPaintEvent>

#include <QTimer>
#include <QTimerEvent>
#include<QColor>
#include <QList>
#include <QMouseEvent>

/*
	各种进度条的绘制
*/

class MyProgressBar : public QWidget
{
	Q_OBJECT

public:
	MyProgressBar(QWidget *parent = Q_NULLPTR);
	void myPainter1(QPainter &painter);
	void myPainter2(QPainter &painter);
	void myPainter3(QPainter &painter);
	void myPainter4(QPainter &painter);
protected:
	void paintEvent(QPaintEvent *event) override;
	void timerEvent(QTimerEvent* event) override;
	void mousePressEvent(QMouseEvent *event) override;

private:
	Ui::CustomProgressClass ui;
	int m_timerId;
	int m_nRotationAngle;
	QList<QColor> style2Color;
	qreal arcLength;
	int alpha;//测试阿帕奇通道,就是测试图形的透明度
	QList<QPainterPath> piePathList;
	int pathIndex;
};
#include "CustomProgress.h"
//.cpp文件
#include <QPainter>
#include <QPainterPath>
#include <QRect>
#include <QConicalGradient>
MyProgressBar::MyProgressBar(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	m_timerId = startTimer(5);
	m_nRotationAngle = 0;
	arcLength = 0.0;
	this->alpha = 255;
	pathIndex = 0;
}

void MyProgressBar::myPainter1(QPainter &painter)
{
	QRect rect(-100, -100, 200, 200);
	QConicalGradient conical(0, 0, 0);
	conical.setColorAt(0, QColor("#3BB6FE"));
	//conical.setColorAt(0.5, Qt::blue);
	conical.setColorAt(1, QColor("#FFFFFF"));

	painter.translate(width() / 2, height() / 2);
	painter.rotate(m_nRotationAngle);
	painter.setRenderHint(QPainter::Antialiasing);
	painter.setPen(Qt::NoPen);
	painter.setBrush(conical);
	QPainterPath arcBigPath;
	arcBigPath.moveTo(0, 0);
	arcBigPath.arcTo(rect, 0, 270);
	QRect rect2(-90, -90, 180, 180);
	QPainterPath arcPath;
	arcPath.moveTo(0, 0);
	arcPath.arcTo(rect2, 0, 270);
	QPainterPath outPath;
	outPath = arcBigPath - arcPath;
	painter.drawPath(outPath);
}

void MyProgressBar::myPainter2(QPainter &painter)
{
	QRect bigRect(-100, -100, 200, 200);
	QRect smallRect(-90, -90, 180, 180);
	painter.translate(width() / 2, height() / 2);
	QPainterPath pathBigEllipse;
	pathBigEllipse.addEllipse(bigRect);
	QPainterPath pathSmallEllipse;
	pathSmallEllipse.addEllipse(smallRect);

	painter.setBrush(Qt::white);
	painter.setPen(Qt::SolidLine);

	QPainterPath outPath = pathBigEllipse - pathSmallEllipse;
	painter.drawPath(outPath);

	painter.save();
	QPainterPath piePath;
	piePath.arcTo(bigRect, 0, arcLength);
	QPainterPath out2 = outPath.intersected(piePath);

	painter.setPen(Qt::SolidLine);
	painter.setBrush(Qt::gray);
	painter.drawPath(out2);

	painter.restore();

	QPainterPath textPath;
	QFont font("Times");
	textPath.addText(QPoint(-60, 0.0), font, QStringLiteral("当前进度:") + QString::number(int(this->arcLength / 360 * 100)) + "%");
	painter.drawPath(textPath);


}

void MyProgressBar::myPainter3(QPainter &painter)
{
	QColor color(121, 65, 13, this->alpha);
	painter.setBrush(color);
	painter.setPen(Qt::NoPen);
	painter.drawEllipse(100, 100, 200, 200);

}

void MyProgressBar::myPainter4(QPainter &painter)
{
	painter.translate(width() / 2, height() / 2);
	painter.setBrush(Qt::gray);
	QRect bigRect(-100, -100, 200, 200);
	QPainterPath bigEllipse;
	bigEllipse.addEllipse(bigRect);

	QPainterPath samllEllipse;
	QRect smallRect(-90, -90, 180, 180);
	samllEllipse.addEllipse(smallRect);

	QPainterPath out1 = bigEllipse - samllEllipse;

	for (int i = 0; i < 6; i++)
	{
		QPainterPath piePath;
		piePath.arcTo(bigRect, i * 60, 30);
		piePath.closeSubpath();
		piePathList.push_back(piePath.intersected(out1));  //将六个不同的扇形放到数组里
	}
	painter.setBrush(Qt::red);
	for (int i = 0; i < piePathList.size(); i++)
	{
		painter.drawPath(piePathList.at(i));
	}
	if (this->pathIndex == piePathList.size())
	{
		this->pathIndex = 0;
	}
	painter.setBrush(Qt::white);
	painter.drawPath(piePathList.at(this->pathIndex));
	pathIndex++;
}

void MyProgressBar::paintEvent(QPaintEvent *event)
{

	QPainter painter(this);
	myPainter4(painter);
}

void MyProgressBar::timerEvent(QTimerEvent* event)
{
	if (event->timerId() == m_timerId)
	{
		m_nRotationAngle++;
		arcLength++;
		if (m_nRotationAngle > 360)
		{
			m_nRotationAngle = 0;
			arcLength = 0;
		}
		update();
	}
}

void MyProgressBar::mousePressEvent(QMouseEvent *event)
{
	if (alpha == 0)
	{
		alpha = 255;
	}
	this->alpha--;
	update();
}

在这个程序中,有3个绘制函数是有用的,那个myPainter3方法是我没有做完的实验,mousePressEvent鼠标按下事件这个方法我本来是想测试下阿帕奇通道的,最后也没有用。

为了使绘制的进度条动起来,我在构造函数中使用startTimer函数开启一个定时器,并实现timerEvent定时器事件,在这个事件中设置参数和持续刷新界面。

现在开始讲解第一个进度条的原理,对应方法myPainter1。

Qt中很容易实现两个图形的交并差的基础图形操作,第一个进度条首先采用的是渐变画刷,其次,用两个270度的扇形,一个大一个小,然后两个相减,就是代码中的outPath = arcBigPath - arcPath;这就实现了进度条的图形区域。如果想要实现其他复杂的图形,QPainterPath这个类你值得深究。在准备好后,在paintEvent这个绘制事件中调用一下就行了。

在myPainter2和myPainter4中也是用了相同的方法,使用多个图形做交并差运算得到对应的图形,然后在进行绘制。需要注意intersected这个函数,其功能是计算两个图形相交后的图形的路径,也就是保存相交后图形的位置,这也是QPainterPath类中的方法,还是那句话,如果想要创造出比较复杂的图形QPainterPath类必不可少。

总的来说,Qt自带的图形计算函数帮我们减少了很多麻烦,接下来我将继续发布我在实习公司所作的Qt绘制实验。

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DreamXY12

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值