zoukankan      html  css  js  c++  java
  • Qt编写自定义控件3-速度仪表盘

    前言

    速度仪表盘,写作之初的本意是用来展示当前测试的网速用的,三色圆环+数码管显示当前速度,Qt自带了数码管控件QLCDNumber,直接集成即可,同时还带有动画功能,其实也可以用在汽车+工业领域等,展示汽车的当前速度和各种指标情况,比如生成领域的完成百分比等,控件采用纯painter绘制,自由拉伸不变形,背景透明的,贴上个背景图就会显得更漂亮。

    实现的功能

    • 1:可设置范围值,支持负数值
    • 2:可设置精确度,最大支持小数点后3位
    • 3:可设置大刻度数量/小刻度数量
    • 4:可设置开始旋转角度/结束旋转角度
    • 5:可设置是否启用动画效果以及动画效果每次移动的步长
    • 6:可设置三色圆环占比例
    • 7:自适应窗体拉伸,刻度尺和文字自动缩放

    效果图

    头文件代码

    #ifndef GAUGESPEED_H
    #define GAUGESPEED_H
    
    /**
     * 速度仪表盘控件 作者:feiyangqingyun(QQ:517216493) 2016-12-31
     * 1:可设置范围值,支持负数值
     * 2:可设置精确度,最大支持小数点后3位
     * 3:可设置大刻度数量/小刻度数量
     * 4:可设置开始旋转角度/结束旋转角度
     * 5:可设置是否启用动画效果以及动画效果每次移动的步长
     * 6:可设置三色圆环占比例
     * 7:自适应窗体拉伸,刻度尺和文字自动缩放
     */
    
    #include <QWidget>
    
    class QLCDNumber;
    
    #ifdef quc
    #if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
    #include <QtDesigner/QDesignerExportWidget>
    #else
    #include <QtUiPlugin/QDesignerExportWidget>
    #endif
    
    class QDESIGNER_WIDGET_EXPORT GaugeSpeed : public QWidget
    #else
    class GaugeSpeed : 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 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(int ringStartPercent READ getRingStartPercent WRITE setRingStartPercent)
        Q_PROPERTY(int ringMidPercent READ getRingMidPercent WRITE setRingMidPercent)
        Q_PROPERTY(int ringEndPercent READ getRingEndPercent WRITE setRingEndPercent)
    
        Q_PROPERTY(QColor ringColorStart READ getRingColorStart WRITE setRingColorStart)
        Q_PROPERTY(QColor ringColorMid READ getRingColorMid WRITE setRingColorMid)
        Q_PROPERTY(QColor ringColorEnd READ getRingColorEnd WRITE setRingColorEnd)
    
        Q_PROPERTY(QColor pointerColor READ getPointerColor WRITE setPointerColor)
        Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
    
    public:
        explicit GaugeSpeed(QWidget *parent = 0);
        ~GaugeSpeed();
    
    protected:
        void resizeEvent(QResizeEvent *);
        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;                //最小值
        double maxValue;                //最大值
        double value;                   //目标值
        int precision;                  //精确度,小数点后几位
    
        int scaleMajor;                 //大刻度数量
        int scaleMinor;                 //小刻度数量
        int startAngle;                 //开始旋转角度
        int endAngle;                   //结束旋转角度
    
        bool animation;                 //是否启用动画显示
        double animationStep;           //动画显示时步长
    
        int ringWidth;                  //圆环宽度
        int ringStartPercent;           //第一圆环比例
        int ringMidPercent;             //第二圆环比例
        int ringEndPercent;             //第三圆环比例
    
        QColor ringColorStart;          //第一圆环颜色
        QColor ringColorMid;            //第二圆环颜色
        QColor ringColorEnd;            //第三圆环颜色
    
        QColor pointerColor;            //指针颜色
        QColor textColor;               //文字颜色
    
        bool reverse;                   //是否往回走
        double currentValue;            //当前值
        QTimer *timer;                  //定时器绘制动画
        QLCDNumber *lcd;                //数码管
    
    public:   
        double getMinValue()            const;
        double getMaxValue()            const;
        double getValue()               const;
        int getPrecision()              const;
    
        int getScaleMajor()             const;
        int getScaleMinor()             const;
        int getStartAngle()             const;
        int getEndAngle()               const;
    
        bool getAnimation()             const;
        double getAnimationStep()       const;
    
        int getRingWidth()              const;
        int getRingStartPercent()       const;
        int getRingMidPercent()         const;
        int getRingEndPercent()         const;
    
        QColor getRingColorStart()      const;
        QColor getRingColorMid()        const;
        QColor getRingColorEnd()        const;
    
        QColor getPointerColor()        const;
        QColor getTextColor()           const;
    
        QSize sizeHint()                const;
        QSize minimumSizeHint()         const;
    
    public Q_SLOTS:
        //设置范围值
        void setRange(double minValue, double maxValue);
        void setRange(int minValue, int maxValue);
    
        //设置最大最小值
        void setMinValue(double minValue);
        void setMaxValue(double maxValue);
    
        //设置目标值
        void setValue(double value);
        void setValue(int value);
    
        //设置精确度
        void setPrecision(int precision);
    
        //设置主刻度数量
        void setScaleMajor(int scaleMajor);
        //设置小刻度数量
        void setScaleMinor(int scaleMinor);
        //设置开始旋转角度
        void setStartAngle(int startAngle);
        //设置结束旋转角度
        void setEndAngle(int endAngle);
    
        //设置是否启用动画显示
        void setAnimation(bool animation);
        //设置动画显示的步长
        void setAnimationStep(double animationStep);
    
        //设置饼圆宽度
        void setRingWidth(int ringWidth);
    
        //设置三个圆环所占比例
        void setRingStartPercent(int ringStartPercent);
        void setRingMidPercent(int ringMidPercent);
        void setRingEndPercent(int ringEndPercent);
    
        //设置三个圆环颜色
        void setRingColorStart(const QColor &ringColorStart);
        void setRingColorMid(const QColor &ringColorMid);
        void setRingColorEnd(const QColor &ringColorEnd);
    
        //设置指针颜色
        void setPointerColor(const QColor &pointerColor);
        //设置文本颜色
        void setTextColor(const QColor &textColor);
    
    Q_SIGNALS:
        void valueChanged(int value);
    };
    
    #endif //GAUGESPEED_H
    
    

    核心代码

    void GaugeSpeed::drawRing(QPainter *painter)
    {
        int radius = 100;
        painter->save();
    
        QPen pen;
        pen.setCapStyle(Qt::FlatCap);
        pen.setWidthF(ringWidth);
    
        radius = radius - ringWidth;
        QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
    
        //计算总范围角度,根据占比例自动计算三色圆环范围角度
        double angleAll = 360.0 - startAngle - endAngle;
        double angleStart = angleAll * (double)ringStartPercent / 100;
        double angleMid = angleAll * (double)ringMidPercent / 100;
        double angleEnd = angleAll * (double)ringEndPercent / 100;
    
        //绘制第一圆环
        pen.setColor(ringColorStart);
        painter->setPen(pen);
        painter->drawArc(rect, (270 - startAngle - angleStart) * 16, angleStart * 16);
    
        //绘制第二圆环
        pen.setColor(ringColorMid);
        painter->setPen(pen);
        painter->drawArc(rect, (270 - startAngle - angleStart - angleMid) * 16, angleMid * 16);
    
        //绘制第三圆环
        pen.setColor(ringColorEnd);
        painter->setPen(pen);
        painter->drawArc(rect, (270 - startAngle - angleStart - angleMid - angleEnd) * 16, angleEnd * 16);
    
        painter->restore();
    }
    
    void GaugeSpeed::drawScale(QPainter *painter)
    {
        int radius = 94;
        painter->save();
    
        QPen pen;
        pen.setColor(textColor);
        pen.setCapStyle(Qt::RoundCap);
    
        painter->rotate(startAngle);
        int steps = (scaleMajor * scaleMinor);
        double angleStep = (360.0 - startAngle - endAngle) / steps;
    
        //计算圆环对应大刻度范围索引
        int indexStart = steps * (double)ringStartPercent / 100 + 1;
        int indexMid = steps * (double)ringMidPercent / 100 - 1;
        int indexEnd = steps * (double)ringEndPercent / 100 + 1;
        int index = 0;
    
        for (int i = 0; i <= steps; i++) {
            if (i % scaleMinor == 0) {
                //根据所在圆环范围切换颜色
                if (index < indexStart) {
                    pen.setColor(ringColorStart);
                } else if (index < (indexStart + indexMid)) {
                    pen.setColor(ringColorMid);
                } else if (index < (indexStart + indexMid + indexEnd)) {
                    pen.setColor(ringColorEnd);
                }
    
                index++;
    
                pen.setWidthF(1.5);
                painter->setPen(pen);
                painter->drawLine(0, radius - 13, 0, radius);
            } else {
                pen.setWidthF(0.5);
                painter->setPen(pen);
                painter->drawLine(0, radius - 5, 0, radius);
            }
    
            painter->rotate(angleStep);
        }
    
        painter->restore();
    }
    
    void GaugeSpeed::drawScaleNum(QPainter *painter)
    {
        int radius = 70;
        painter->save();
        painter->setPen(textColor);
    
        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("%1M").arg((double)value, 0, 'f', 0);
            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 GaugeSpeed::drawPointer(QPainter *painter)
    {
        int radius = 62;
        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();
    }
    
    

    控件介绍

    1. 超过130个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。
    2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。
    3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.12的任何Qt版本,支持mingw、msvc、gcc等编译器,不乱码,可直接集成到Qt Creator中,和自带的控件一样使用,大部分效果只要设置几个属性即可,极为方便。
    4. 每个控件都有一个对应的单独的包含该控件源码的DEMO,方便参考使用。同时还提供一个所有控件使用的集成的DEMO。
    5. 每个控件的源代码都有详细中文注释,都按照统一设计规范编写,方便学习自定义控件的编写。
    6. 每个控件默认配色和demo对应的配色都非常精美。
    7. 超过120个可见控件,6个不可见控件。
    8. 部分控件提供多种样式风格选择,多种指示器样式选择。
    9. 所有控件自适应窗体拉伸变化。
    10. 集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。
    11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。
    12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。
    13. 所有控件最后生成一个dll动态库文件,可以直接集成到qtcreator中拖曳设计使用。

    SDK下载


  • 相关阅读:
    CodeForces Gym 100935G Board Game DFS
    CodeForces 493D Vasya and Chess 简单博弈
    CodeForces Gym 100935D Enormous Carpet 快速幂取模
    CodeForces Gym 100935E Pairs
    CodeForces Gym 100935C OCR (水
    CodeForces Gym 100935B Weird Cryptography
    HDU-敌兵布阵
    HDU-Minimum Inversion Number(最小逆序数)
    七月馒头
    非常可乐
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/10743960.html
Copyright © 2011-2022 走看看