Qt Writes Custom Control 32 - Waiting for Progress Bar Control

Keywords: Mobile Qt SDK Qt5 Linux

I. Preface

In a variety of task interfaces, sometimes it takes more time to give an intuitive waiting progress bar to show the progress of the current execution, instead of being forced there, users will not feel dead or why. There are several ways to wait for the progress bar, such as directly asking the artist to do the gif map, using QLabel and QMovie to load the gif picture. This method is the simplest and most convenient, or to do a lot of progress bar pictures, using timing mapping to achieve, these methods are not flexible enough, write dead, for example, sometimes. Need to change the color or display form, and need the artist to redo the drawing, the torture is deadly. At that time, when writing the waiting progress bar, we considered integrating various styles for users to choose, such as arc style, rotating circle style, triangular arc, line style, circle style, etc. One control is equivalent to five or six controls, which is more powerful, and the code is complete and brilliant.

II. Functions of Realization

  • 1: Support a variety of waiting style arc style rotary circular style triangular arc style ring style
  • 2: Range values and current values can be set
  • 3: Foreground color and background color can be set
  • 4: Clockwise and counterclockwise rotation can be set
  • 5: Support arbitrary scaling
  • 6: Support setting rotation speed interval

III. EFFECT CHARACTERISTICS

Header file code

#ifndef PROGRESSWAIT_H
#define PROGRESSWAIT_H

/**
 * Waiting for progress bar control author: feiyangqingyun(QQ:517216493) 2016-10-28
 * 1:Support a variety of waiting style arc style rotary circle style triangular arc style ring style
 * 2:Settable range values and current values
 * 3:Settable foreground and background colors
 * 4:Clockwise and counterclockwise rotation can be set
 * 5:Support arbitrary scaling
 * 6:Support setting rotation speed interval
 */

#include <QWidget>

#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif

class QDESIGNER_WIDGET_EXPORT ProgressWait : public QWidget
#else
class ProgressWait : public QWidget
#endif

{
	Q_OBJECT
	Q_ENUMS(BarStyle)

	Q_PROPERTY(bool clockWise READ getClockWise WRITE setClockWise)
	Q_PROPERTY(bool showPercent READ getShowPercent WRITE setShowPercent)

	Q_PROPERTY(int currentValue READ getCurrentValue WRITE setCurrentValue)
	Q_PROPERTY(int maxValue READ getMaxValue WRITE setMaxValue)
	Q_PROPERTY(int interval READ getInterval WRITE setInterval)

	Q_PROPERTY(BarStyle barStyle READ getBarStyle WRITE setBarStyle)
	Q_PROPERTY(QColor background READ getBackground WRITE setBackground)
	Q_PROPERTY(QColor foreground READ getForeground WRITE setForeground)
    Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)

public:
	enum BarStyle {
		BarStyle_Arc = 0,           //Arc Style
		BarStyle_RoundCircle = 1,   //Rotating Circle Style
		BarStyle_Pie = 2,           //Triangular Arc Style
		BarStyle_Line = 3,          //Line Style
		BarStyle_Ring = 4,          //Ring Style
		BarStyle_SingleCircle = 5,  //A circle flickers
		BarStyle_DoubleCircle = 6   //Two circles twinkle
	};

	ProgressWait(QWidget *parent = 0);
	~ProgressWait();

protected:
	void resizeEvent(QResizeEvent *);
	void paintEvent(QPaintEvent *);
	void drawArc(QPainter *painter);
	void drawRoundCircle(QPainter *painter);
	void drawPie(QPainter *painter);
	void drawLine(QPainter *painter);
	void drawRing(QPainter *painter);
	void drawSingleCircle(QPainter *painter);
	void drawDoubleCircle(QPainter *painter);
    void drawValue(QPainter *painter);

private:
	bool clockWise;                 //Clockwise and counterclockwise
	bool showPercent;               //Display current percentage
	int currentValue;               //Current value
	int maxValue;                   //Maximum
	int interval;                   //Rotation interval

	int minRadius;                  //Minimum radius
	int maxRadius;                  //Maximum radius
	int offsetRadius;               //Radius offset
	int leftRadius;                 //Left radius of circle
	int rightRadius;                //Right circle radius
	bool leftIncrease;              //Left Incremental
	bool rightIncrease;             //Incremental increase to the right

	BarStyle barStyle;              //style
	QColor background;              //background color
	QColor foreground;              //Foreground color
    QColor textColor;               //Text color

	QTimer *timer;                  //Timer Drawing

private:
	double degreesToRadians(double value);

private slots:
	void updateValue();

public:
	bool getClockWise()             const;
	bool getShowPercent()           const;
	int getCurrentValue()           const;
	int getMaxValue()               const;
	int getInterval()               const;

	BarStyle getBarStyle()          const;
	QColor getBackground()          const;
	QColor getForeground()          const;
    QColor getTextColor()           const;

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

public Q_SLOTS:
	//Set clockwise and counterclockwise rotation
	void setClockWise(bool clockWise);
	//Set whether percentage is displayed
	void setShowPercent(bool showPercent);
	//set currency
	void setCurrentValue(int currentValue);
	//Set maximum
	void setMaxValue(int maxValue);
	//Set the rotation speed interval
	void setInterval(int interval);

	//Setting Styles
    void setBarStyle(const BarStyle &barStyle);
	//set foreground color
	void setBackground(const QColor &background);
	//set foreground color
	void setForeground(const QColor &foreground);
    //Setting text color
    void setTextColor(const QColor &textColor);
};

#endif // PROGRESSWAIT_H


V. Core Code

void ProgressWait::paintEvent(QPaintEvent *)
{
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    //Drawing preparation, enabling anti-aliasing, translating coordinate axis center, scaling in equal proportion
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.translate(width / 2, height / 2);
    painter.scale(side / 200.0, side / 200.0);

    if (barStyle == BarStyle_Arc) {
        drawArc(&painter);
    } else if (barStyle == BarStyle_RoundCircle) {
        drawRoundCircle(&painter);
    } else if (barStyle == BarStyle_Pie) {
        drawPie(&painter);
    } else if (barStyle == BarStyle_Line) {
        drawLine(&painter);
    } else if (barStyle == BarStyle_Ring) {
        drawRing(&painter);
    } else if (barStyle == BarStyle_SingleCircle) {
        drawSingleCircle(&painter);
    } else if (barStyle == BarStyle_DoubleCircle) {
        drawDoubleCircle(&painter);
    }

    drawValue(&painter);
}

void ProgressWait::drawArc(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    //Calculating the coordinates of the central point
    int centerX = 0;
    int centerY = 0;
    int radius = 99;
    int radiusBig = radius / 2;
    int radiusSmall = radius / 6;
    double currentangle = currentValue * (360 / (maxValue + 1));

    if (clockWise) {
        currentangle = -currentangle;
    }

    //Drawing the Big Circle of Eight Diagrams
    painter->setBrush(foreground);
    QPainterPath pathBig1(QPointF(centerX + radius * qCos(degreesToRadians(currentangle)),
                                  centerY - radius * qSin(degreesToRadians(currentangle))));
    pathBig1.arcTo(centerX - radius, centerY - radius, radius * 2, radius * 2, currentangle, 180);
    pathBig1.arcTo(centerX + radiusBig * qCos(degreesToRadians(currentangle + 180)) - radiusBig,
                   centerY - radiusBig * qSin(degreesToRadians(currentangle + 180)) - radiusBig,
                   radiusBig * 2, radiusBig * 2, currentangle + 180, 180);
    pathBig1.arcTo(centerX + radiusBig * qCos(degreesToRadians(currentangle)) - radiusBig,
                   centerY - radiusBig * qSin(degreesToRadians(currentangle)) - radiusBig,
                   radiusBig * 2, radiusBig * 2, currentangle + 180, -180
                  );
    painter->drawPath(pathBig1);

    //Drawing the Big Circle of Eight Diagrams 2
    painter->setBrush(background);
    QPainterPath pathBig2(QPointF(centerX + radius * qCos(degreesToRadians(currentangle)),
                                  centerY - radius * qSin(degreesToRadians(currentangle))));
    pathBig2.arcTo(centerX - radius, centerY - radius, radius * 2, radius * 2, currentangle, -180);
    pathBig2.arcTo(centerX + radiusBig * qCos(degreesToRadians(currentangle + 180)) - radiusBig,
                   centerY - radiusBig * qSin(degreesToRadians(currentangle + 180)) - radiusBig,
                   radiusBig * 2, radiusBig * 2, currentangle + 180, 180);
    pathBig2.arcTo(centerX + radiusBig * qCos(degreesToRadians(currentangle)) - radiusBig,
                   centerY - radiusBig * qSin(degreesToRadians(currentangle)) - radiusBig,
                   radiusBig * 2, radiusBig * 2, currentangle + 180, -180
                  );
    painter->drawPath(pathBig2);

    //Drawing Bagua Little Circle 1
    painter->setBrush(foreground);
    QPainterPath pathSmall1;
    pathSmall1.addEllipse(centerX + radiusBig * qCos(degreesToRadians(currentangle)) - radiusSmall,
                          centerY - radiusBig * qSin(degreesToRadians(currentangle)) - radiusSmall,
                          radiusSmall * 2, radiusSmall * 2);
    painter->drawPath(pathSmall1);

    //Drawing Bagua Small Circle 2
    painter->setBrush(background);
    QPainterPath pathSmall2;
    pathSmall2.addEllipse(centerX + radiusBig * qCos(degreesToRadians(180 + currentangle)) - radiusSmall,
                          centerY - radiusBig * qSin(degreesToRadians(180 + currentangle)) - radiusSmall,
                          radiusSmall * 2, radiusSmall * 2);
    painter->drawPath(pathSmall2);

    painter->restore();
}

void ProgressWait::drawRoundCircle(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    int radius = 99;
    int minRadius = radius / 6;
    double angleStep = 360.0 / maxValue;
    double alpha = (double)1 / maxValue;

    if (!clockWise) {
        angleStep = -angleStep;
    }

    //Calculating the coordinates of the central point
    int centerX = 0;
    int centerY = 0;
    double centerRadius = radius / 1.2;

    for (int i = 0; i < maxValue; i++) {
        double angle = (currentValue + i) * angleStep;
        double initX = centerRadius * qCos(degreesToRadians(angle)) + centerX;
        double initY = centerRadius * qSin(degreesToRadians(angle)) + centerY;

        int value = i * alpha * 255;
        value = value < 30 ? 30 : value;

        foreground.setAlpha(value);
        painter->setBrush(foreground);
        painter->drawEllipse(initX - minRadius, initY - minRadius, minRadius * 2, minRadius * 2);
    }

    painter->restore();
}

Introduction of Control

  1. More than 149 exquisite controls, covering a variety of dashboards, progress bars, progress balls, compasses, curves, rulers, thermometers, navigation bars, navigation bars, flatui, highlighted buttons, sliding selectors, the lunar calendar and so on. Far more controls than qwt integrates.
  2. Each class can be separated into a separate control, zero-coupling, each control has a header file and an implementation file, independent of other files, to facilitate the integration of a single control in the form of source code into the project, less code. The control classes of qwt are interlinked and highly coupled. If you want to use one of the controls, you must include all the code.
  3. All pure Qt writing, QWidget+QPainter drawing, support any Qt version from Qt4.6 to Qt5.12, support mingw, msvc, gcc and other compilers, support any operating system such as windows+linux+mac + embedded linux, no scrambling, can be directly integrated into Qt Creator, as with its own controls, most of the effects as long as set up. Several attributes can be used, which is very convenient.
  4. Each control has a corresponding separate DEMO containing the source code of the control, which is convenient for reference. It also provides an integrated DEMO for all controls.
  5. The source code of each control has detailed Chinese annotations, which are compiled in accordance with the unified design specifications. It is convenient to learn how to compile custom controls.
  6. Each control's default color matching and demo's corresponding color matching are very beautiful.
  7. More than 130 visible controls and 6 invisible controls.
  8. Some controls provide a variety of style choices, a variety of indicator style choices.
  9. All controls adapt to form stretching changes.
  10. Integrate custom control property designer, support drag design, WYSIWYG, support import and export xml format.
  11. With activex control demo, all controls can run directly in ie browser.
  12. Integrate fontawesome graphic fonts + hundreds of graphic fonts collected by Alibaba iconfont to enjoy the fun of graphic fonts.
  13. All controls finally generate a dll Dynamic Library file, which can be directly integrated into the qtcreator for dragging design use.
  14. At present, there is a version of qml, pyqt version will be considered later, if the user demand is large.

7. SDK Download

  • SDK Download Link: https://pan.baidu.com/s/1A5Gd77kExm8Co5ckT51vvQ Extraction code: 877p
  • The download link contains various versions of dynamic library files, header files of all controls, using demo, custom control + property designer.
  • Custom control plug-in open dynamic library dll use (permanent free), without any back door and restrictions, please feel free to use.
  • At present, 26 versions of dll have been provided, including qt5.12.3 MSVC 2017 32 + 64 MinGW 32 + 64.
  • Increase control and improve control from time to time, update SDK from time to time. Welcome to make suggestions. Thank you!
  • widget version (QQ: 517216493) qml version (QQ: 373955953) camel (QQ: 278969898).
  • The Way to Advance Qt in Taoge's Knowledge Column https://zhuanlan.zhihu.com/TaoQt
  • Welcome to pay attention to Wechat Public Number, C++/Python, learning methods, writing skills, popular technology, career development and other content, more dry goods, more benefits!

Posted by slak on Sat, 20 Jul 2019 23:56:43 -0700