Qt Writing Custom Control 31-Panel Dashboard Control

Keywords: Mobile Qt SDK Qt5 Linux

I. Preface

In Qt custom control, dashboard control is the largest number, writing dashboards are written about hematemesis, probably because a variety of industrial control areas are more used, and the dashboard is more vivid and intuitive, this time see Baidu echart has this control, so also to imitate and do a, in fact, master it. After the drawing method of one or two dashboards, the drawing of other dashboards is like a fish in water, and basically changes little. To sum up, there are the following points: 1: dashboard border 2: Scale 3: Scale value 4: Ring Progress 5: Pointer 6: Current value 7: Dashboard Title No matter what dashboard, it basically contains most of the above elements, so as long as you master the drawing of several elements, any dashboard drawing is easy to handle. Some dashboards require calibration rulers to be inside and outside, some require different color display of ring progress, some require custom left start angle and right end angle, some require pointer circular square ellipse, and some require slow animation transition when the value changes. Effectiveness, etc.

II. Functions of Realization

  • 1: Range values can be set to support negative values
  • 2: Can set accuracy + scale accuracy, maximum support decimal point after 3 bits
  • 3: Large scale/small scale can be set
  • 4: Start rotation angle/end rotation angle can be set
  • 5: Can set whether animation effect is enabled and the step size of animation effect each time it moves
  • 6: Scale color + Text color + Ring width and color can be set
  • 7: Self-adaptive form stretching, scale and text auto-zooming
  • 8: Settable unit and dashboard name

III. EFFECT CHARACTERISTICS

Header file code

#ifndef GAUGEPANEL_H
#define GAUGEPANEL_H

/**
 * Author of panel dashboard control: Feiyang Qingyun (QQ: 517216493) 2019-7-3
 * 1:Range values can be set to support negative values
 * 2:Can be set up accuracy + scale accuracy, maximum support decimal point after 3 bits
 * 3:Large scale number/small scale number can be set
 * 4:Start rotation angle/end rotation angle can be set
 * 5:Can set whether animation effect is enabled and the step size of animation effect each time it moves
 * 6:Scale color + text color + ring width and color can be set
 * 7:Self-adaptive form stretching, scale and text auto-zooming
 * 8:Settable unit and dashboard name
 */

#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 GaugePanel : public QWidget
#else
class GaugePanel : public QWidget
#endif

{
    Q_OBJECT
    Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
    Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue)
    Q_PROPERTY(double value READ getValue WRITE setValue)
    Q_PROPERTY(int precision READ getPrecision WRITE setPrecision)
    Q_PROPERTY(int scalePrecision READ getScalePrecision WRITE setScalePrecision)

    Q_PROPERTY(int scaleMajor READ getScaleMajor WRITE setScaleMajor)
    Q_PROPERTY(int scaleMinor READ getScaleMinor WRITE setScaleMinor)
    Q_PROPERTY(int startAngle READ getStartAngle WRITE setStartAngle)
    Q_PROPERTY(int endAngle READ getEndAngle WRITE setEndAngle)

    Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation)
    Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep)

    Q_PROPERTY(int ringWidth READ getRingWidth WRITE setRingWidth)
    Q_PROPERTY(QColor ringColor READ getRingColor WRITE setRingColor)

    Q_PROPERTY(QColor scaleColor READ getScaleColor WRITE setScaleColor)
    Q_PROPERTY(QColor pointerColor READ getPointerColor WRITE setPointerColor)
    Q_PROPERTY(QColor bgColor READ getBgColor WRITE setBgColor)
    Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
    Q_PROPERTY(QString unit READ getUnit WRITE setUnit)
    Q_PROPERTY(QString text READ getText WRITE setText)

public:
    explicit GaugePanel(QWidget *parent = 0);
    ~GaugePanel();

protected:
    void paintEvent(QPaintEvent *);
    void drawRing(QPainter *painter);
    void drawScale(QPainter *painter);
    void drawScaleNum(QPainter *painter);
    void drawPointer(QPainter *painter);
    void drawValue(QPainter *painter);

private slots:
    void updateValue();

private:    
    double minValue;                //minimum value
    double maxValue;                //Maximum
    double value;                   //target value
    int precision;                  //Accuracy, after decimal points
    int scalePrecision;             //Calibration scale accuracy, decimal point after several bits

    int scaleMajor;                 //Large scale quantity
    int scaleMinor;                 //Small scale quantity
    int startAngle;                 //Start rotation angle
    int endAngle;                   //End rotation angle

    bool animation;                 //Whether animation display is enabled
    double animationStep;           //Time step of animation display

    int ringWidth;                  //Ring width
    QColor ringColor;               //Ring color

    QColor scaleColor;              //Calibration colour
    QColor pointerColor;            //Pointer color
    QColor bgColor;                 //background color
    QColor textColor;               //Text color
    QString unit;                   //Company
    QString text;                   //Descriptive Text

    bool reverse;                   //Whether to go back or not
    double currentValue;            //Current value
    QTimer *timer;                  //Timer Drawing Animation

public:   
    double getMinValue()            const;
    double getMaxValue()            const;
    double getValue()               const;
    int getPrecision()              const;
    int getScalePrecision()         const;

    int getScaleMajor()             const;
    int getScaleMinor()             const;
    int getStartAngle()             const;
    int getEndAngle()               const;

    bool getAnimation()             const;
    double getAnimationStep()       const;

    int getRingWidth()              const;
    QColor getRingColor()           const;

    QColor getScaleColor()          const;
    QColor getPointerColor()        const;
    QColor getBgColor()             const;
    QColor getTextColor()           const;
    QString getUnit()               const;
    QString getText()               const;

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

public Q_SLOTS:
    //Set range values
    void setRange(double minValue, double maxValue);
    void setRange(int minValue, int maxValue);

    //Set maximum and minimum
    void setMinValue(double minValue);
    void setMaxValue(double maxValue);

    //Setting target values
    void setValue(double value);
    void setValue(int value);

    //Setting Accuracy
    void setPrecision(int precision);
    //Setting scale accuracy
    void setScalePrecision(int scalePrecision);

    //Setting the number of primary scales
    void setScaleMajor(int scaleMajor);
    //Set the number of small scales
    void setScaleMinor(int scaleMinor);
    //Set the start rotation angle
    void setStartAngle(int startAngle);
    //Set the end rotation angle
    void setEndAngle(int endAngle);

    //Set whether animation display is enabled
    void setAnimation(bool animation);
    //Set the step size for animation display
    void setAnimationStep(double animationStep);

    //Set Ring Width + Color
    void setRingWidth(int ringWidth);
    void setRingColor(const QColor &ringColor);

    //Setting scale color
    void setScaleColor(const QColor &scaleColor);
    //Setting the pointer color
    void setPointerColor(const QColor &pointerColor);
    //Set the background color
    void setBgColor(const QColor &bgColor);
    //Setting Text Colors
    void setTextColor(const QColor &textColor);
    //Setting up units
    void setUnit(const QString &unit);
    //Setting Intermediate Description Text
    void setText(const QString &text);

Q_SIGNALS:
    void valueChanged(int value);
};

#endif // GAUGEPANEL_H


V. Core Code

void GaugePanel::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);

    //Drawing Background
    if (bgColor != Qt::transparent) {
        painter.setPen(Qt::NoPen);
        painter.fillRect(this->rect(), bgColor);
    }

    painter.translate(width / 2, height / 2);
    painter.scale(side / 200.0, side / 200.0);

    //donut
    drawRing(&painter);

    //Drawing scale lines
    drawScale(&painter);

    //Drawing scale values
    drawScaleNum(&painter);

    //Drawing Indicator
    drawPointer(&painter);

    //Draw the current value
    drawValue(&painter);
}

void GaugePanel::drawRing(QPainter *painter)
{
    int radius = 70;
    painter->save();

    QPen pen;
    pen.setCapStyle(Qt::FlatCap);
    pen.setWidthF(ringWidth);
    pen.setColor(ringColor);
    painter->setPen(pen);

    radius = radius - ringWidth;
    QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
    double angleAll = 360.0 - startAngle - endAngle;
    painter->drawArc(rect, (270 - startAngle - angleAll) * 16, angleAll * 16);

    painter->restore();
}

void GaugePanel::drawScale(QPainter *painter)
{
    int radius = 80;
    painter->save();

    painter->rotate(startAngle);
    int steps = (scaleMajor * scaleMinor);
    double angleStep = (360.0 - startAngle - endAngle) / steps;

    QPen pen;
    pen.setCapStyle(Qt::RoundCap);
    pen.setColor(scaleColor);

    for (int i = 0; i <= steps; i++) {
        if (i % scaleMinor == 0) {
            pen.setWidthF(1.5);
            painter->setPen(pen);
            painter->drawLine(0, radius - 8, 0, radius + 5);
        } else {
            pen.setWidthF(0.5);
            painter->setPen(pen);
            painter->drawLine(0, radius - 8, 0, radius - 3);
        }

        painter->rotate(angleStep);
    }

    painter->restore();
}

void GaugePanel::drawScaleNum(QPainter *painter)
{
    int radius = 95;
    painter->save();
    painter->setPen(scaleColor);

    double startRad = (360 - startAngle - 90) * (M_PI / 180);
    double deltaRad = (360 - startAngle - endAngle) * (M_PI / 180) / scaleMajor;

    for (int i = 0; i <= scaleMajor; i++) {
        double sina = qSin(startRad - i * deltaRad);
        double cosa = qCos(startRad - i * deltaRad);
        double value = 1.0 * i * ((maxValue - minValue) / scaleMajor) + minValue;

        QString strValue = QString("%1").arg((double)value, 0, 'f', scalePrecision);
        double textWidth = fontMetrics().width(strValue);
        double textHeight = fontMetrics().height();
        int x = radius * cosa - textWidth / 2;
        int y = -radius * sina + textHeight / 4;
        painter->drawText(x, y, strValue);
    }

    painter->restore();
}

void GaugePanel::drawPointer(QPainter *painter)
{
    int radius = 70;
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(pointerColor);

    QPolygon pts;
    pts.setPoints(4, -5, 0, 0, -8, 5, 0, 0, radius);

    painter->rotate(startAngle);
    double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
    painter->rotate(degRotate);
    painter->drawConvexPolygon(pts);

    painter->restore();
}

void GaugePanel::drawValue(QPainter *painter)
{
    int radius = 100;
    painter->save();
    painter->setPen(textColor);

    QFont font;
    font.setPixelSize(15);
    painter->setFont(font);

    QString strValue = QString("%1").arg((double)currentValue, 0, 'f', precision);
    strValue = QString("%1 %2").arg(strValue).arg(unit);
    QRectF valueRect(-radius, radius / 3.5, radius * 2, radius / 3.5);
    painter->drawText(valueRect, Qt::AlignCenter, strValue);

    QRectF textRect(-radius, radius / 2.5, radius * 2, radius / 2.5);
    font.setPixelSize(12);
    painter->setFont(font);
    painter->drawText(textRect, Qt::AlignCenter, text);

    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 ChrisFlynn on Sat, 20 Jul 2019 07:21:29 -0700