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_OBJECTpublic: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繪制實驗。
總結
- 上一篇: 80年来最强龙卷风袭击古巴首都 致4死1
- 下一篇: 5计算机设备与环境安全—拓展与应用