• Qt编写自定义控件12-进度仪表盘


    前言

    进度仪表盘主要应用场景是标识一个任务进度完成的状况等,可以自由的设置范围值和当前值,为了美观还提供了四种指示器(圆形指示器/指针指示器/圆角指针指示器/三角形指示器),各种颜色都可以设置,其中的动画效果采用的QPropertyAnimation类来实现,主要是线性插值法,生成一定规则的数值,用于设定的属性。今天有个朋友需要安卓版本的控件,其实采用qwidget写的控件都可以直接编译就可以到android上,于是直接重新编译了安卓版本,对应的apk已上传到共享文件夹,文末贴出android运行效果图。

    实现的功能

    • 1:支持指示器样式选择 圆形指示器/指针指示器/圆角指针指示器/三角形指示器
    • 2:支持鼠标按下旋转改变值
    • 3:支持负数范围值
    • 4:支持设置当前值及范围值
    • 5:支持设置起始旋转角度和结束旋转角度
    • 6:支持设置背景色/进度颜色/中间圆渐变颜色
    • 7:随窗体拉伸自动变化
    • 8:支持鼠标进入和离开动画效果
    • 9:可设置是否显示当前值
    • 10:可设置是否显示指示器

    效果图

    头文件代码

    #ifndef GAUGEPROGRESS_H
    #define GAUGEPROGRESS_H
    
    /**
     * 进度条仪表盘控件 作者:feiyangqingyun(QQ:517216493) 2016-12-03
     * 1:支持指示器样式选择 圆形指示器/指针指示器/圆角指针指示器/三角形指示器
     * 2:支持鼠标按下旋转改变值
     * 3:支持负数范围值
     * 4:支持设置当前值及范围值
     * 5:支持设置起始旋转角度和结束旋转角度
     * 6:支持设置背景色/进度颜色/中间圆渐变颜色
     * 7:随窗体拉伸自动变化
     * 8:支持鼠标进入和离开动画效果
     * 9:可设置是否显示当前值
     * 10:可设置是否显示指示器
     */
    
    #include <QWidget>
    #include <QVariant>
    
    class QPropertyAnimation;
    
    #ifdef quc
    #if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
    #include <QtDesigner/QDesignerExportWidget>
    #else
    #include <QtUiPlugin/QDesignerExportWidget>
    #endif
    
    class QDESIGNER_WIDGET_EXPORT GaugeProgress : public QWidget
    #else
    class GaugeProgress : public QWidget
    #endif
    
    {
    	Q_OBJECT
    	Q_ENUMS(PointerStyle)
    
    	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 startAngle READ getStartAngle WRITE setStartAngle)
    	Q_PROPERTY(int endAngle READ getEndAngle WRITE setEndAngle)
    
    	Q_PROPERTY(QColor bgColor READ getBgColor WRITE setBgColor)
    	Q_PROPERTY(QColor progressColor READ getProgressColor WRITE setProgressColor)
    	Q_PROPERTY(QColor progressBgColor READ getProgressBgColor WRITE setProgressBgColor)
    	Q_PROPERTY(QColor circleColorStart READ getCircleColorStart WRITE setCircleColorStart)
    	Q_PROPERTY(QColor circleColorEnd READ getCircleColorEnd WRITE setCircleColorEnd)
    	Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
    
    	Q_PROPERTY(bool showPointer READ getShowPointer WRITE setShowPointer)
    	Q_PROPERTY(bool showValue READ getShowValue WRITE setShowValue)
    	Q_PROPERTY(PointerStyle pointerStyle READ getPointerStyle WRITE setPointerStyle)
    
    public:
    	enum PointerStyle {
    		PointerStyle_Circle = 0,        //圆形指示器
    		PointerStyle_Indicator = 1,     //指针指示器
    		PointerStyle_IndicatorR = 2,    //圆角指针指示器
    		PointerStyle_Triangle = 3       //三角形指示器
    	};
    
        explicit GaugeProgress(QWidget *parent = 0);
        ~GaugeProgress();
    
    protected:
    	void enterEvent(QEvent *);
    	void leaveEvent(QEvent *);
    	void mousePressEvent(QMouseEvent *);
    	void mouseReleaseEvent(QMouseEvent *);
    	void mouseMoveEvent(QMouseEvent *);
    	void paintEvent(QPaintEvent *);
    	void drawBg(QPainter *painter);
    	void drawColorPie(QPainter *painter);
    	void drawCoverCircle(QPainter *painter);
    	void drawCircle(QPainter *painter);
    	void drawPointerCircle(QPainter *painter);
    	void drawPointerIndicator(QPainter *painter);
    	void drawPointerIndicatorR(QPainter *painter);
    	void drawPointerTriangle(QPainter *painter);
        void drawValue(QPainter *painter);
    
    private:	
        double minValue;                //最小值
        double maxValue;                //最大值
        double value;                   //目标值
    	int precision;                  //精确度,小数点后几位
    
    	int startAngle;                 //开始旋转角度
    	int endAngle;                   //结束旋转角度
    
    	QColor bgColor;                 //背景色
    	QColor progressColor;           //当前进度颜色
    	QColor progressBgColor;         //进度背景颜色
    	QColor circleColorStart;        //中间圆渐变开始颜色
    	QColor circleColorEnd;          //中间圆渐变结束颜色
    	QColor textColor;               //文字颜色
    
    	bool showPointer;               //是否显示指示器
    	bool showValue;                 //是否显示当前值
    	PointerStyle pointerStyle;      //指针样式
    
    	bool hover;                     //是否鼠标悬停
    	int radiusCoverCircle;          //覆盖圆半径
    	int radiusCircle;               //中间圆半径
    	QPropertyAnimation *animation;  //动画对象
    
    private slots:
    	void setEasingCurve();
    	void updateRadius(QVariant radius);
    
    private:
    	//鼠标是否按下
    	bool pressed;
    	//根据鼠标按下的坐标设置当前按下坐标处的值
    	void setPressedValue(QPointF pressedPoint);
    
    public:	
    	double getMinValue()            const;
    	double getMaxValue()            const;
        double getValue()               const;
    	int getPrecision()              const;
    
    	int getStartAngle()             const;
    	int getEndAngle()               const;
    
    	QColor getBgColor()             const;
    	QColor getProgressColor()       const;
    	QColor getProgressBgColor()     const;
    	QColor getCircleColorStart()    const;
    	QColor getCircleColorEnd()      const;
    	QColor getTextColor()           const;
    
    	bool getShowPointer()           const;
    	bool getShowValue()             const;
    	PointerStyle getPointerStyle()  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 setStartAngle(int startAngle);
    	//设置结束旋转角度
    	void setEndAngle(int endAngle);
    
    	//设置背景色
        void setBgColor(const QColor &bgColor);
    
    	//设置进度颜色
        void setProgressColor(const QColor &progressColor);
        void setProgressBgColor(const QColor &progressBgColor);
    
    	//设置中间圆颜色
        void setCircleColorStart(const QColor &circleColorStart);
        void setCircleColorEnd(const QColor &circleColorEnd);
    
    	//设置文本颜色
        void setTextColor(const QColor &textColor);
    
    	//设置是否显示指示器
    	void setShowPointer(bool showPointer);
    	//设置是否显示当前值
    	void setShowValue(bool showValue);
    	//设置指针样式
        void setPointerStyle(const PointerStyle &pointerStyle);
    
    Q_SIGNALS:
    	void valueChanged(int value);
    };
    
    #endif // GAUGEPROGRESS_H
    
    
    

    核心代码

    void GaugeProgress::paintEvent(QPaintEvent *)
    {
        int width = this->width();
        int height = this->height();
        int side = qMin(width, height);
    
        //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
        QPainter painter(this);
        painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
        painter.translate(width / 2, height / 2);
        painter.scale(side / 200.0, side / 200.0);
    
        //绘制背景
        drawBg(&painter);
        //绘制饼圆
        drawColorPie(&painter);
        //绘制覆盖圆 用以遮住饼圆多余部分
        drawCoverCircle(&painter);
        //绘制中心圆
        drawCircle(&painter);
    
        //根据指示器形状绘制指示器
        if (pointerStyle == PointerStyle_Circle) {
            drawPointerCircle(&painter);
        } else if (pointerStyle == PointerStyle_Indicator) {
            drawPointerIndicator(&painter);
        } else if (pointerStyle == PointerStyle_IndicatorR) {
            drawPointerIndicatorR(&painter);
        } else if (pointerStyle == PointerStyle_Triangle) {
            drawPointerTriangle(&painter);
        }
    
        //绘制当前值
        drawValue(&painter);
    }
    
    void GaugeProgress::drawBg(QPainter *painter)
    {
        int radius = 99;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(bgColor);
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
        painter->restore();
    }
    
    void GaugeProgress::drawColorPie(QPainter *painter)
    {
        int radius = 95;
        painter->save();
        painter->setPen(Qt::NoPen);
    
        QRectF rect(-radius, -radius, radius * 2, radius * 2);
    
        //计算总范围角度,当前值范围角度,剩余值范围角度
        double angleAll = 360.0 - startAngle - endAngle;
        double angleCurrent = angleAll * ((value - minValue) / (maxValue - minValue));
        double angleOther = angleAll - angleCurrent;
    
        //绘制当前值饼圆
        painter->setBrush(progressColor);
        painter->drawPie(rect, (270 - startAngle - angleCurrent) * 16, angleCurrent * 16);
    
        //绘制剩余值饼圆
        painter->setBrush(progressBgColor);
        painter->drawPie(rect, (270 - startAngle - angleCurrent - angleOther) * 16, angleOther * 16);
    
        painter->restore();
    }
    
    void GaugeProgress::drawCoverCircle(QPainter *painter)
    {
        int radius = radiusCoverCircle;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(bgColor);
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
        painter->restore();
    }
    
    void GaugeProgress::drawCircle(QPainter *painter)
    {
        int radius = radiusCircle;
        painter->save();
        painter->setPen(Qt::NoPen);
        QLinearGradient bgGradient(0, -radius, 0, radius);
        bgGradient.setColorAt(0.0, circleColorStart);
        bgGradient.setColorAt(1.0, circleColorEnd);
        painter->setBrush(bgGradient);
    
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
        painter->restore();
    }
    
    void GaugeProgress::drawPointerCircle(QPainter *painter)
    {
        if (!showPointer) {
            return;
        }
    
        int radius = 15;
        int offset = radiusCircle - 60;
        painter->save();
        painter->setPen(Qt::NoPen);
    
        painter->rotate(startAngle);
        double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (value - minValue);
        painter->rotate(degRotate);
    
        painter->setBrush(progressColor);
        painter->drawEllipse(-radius, radius + offset, radius * 2, radius * 2);
    
        painter->restore();
    }
    
    void GaugeProgress::drawPointerIndicator(QPainter *painter)
    {
        if (!showPointer) {
            return;
        }
    
        int radius = radiusCircle - 15;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(progressColor);
    
        QPolygon pts;
        pts.setPoints(3, -8, 0, 8, 0, 0, radius);
    
        painter->rotate(startAngle);
        double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (value - minValue);
        painter->rotate(degRotate);
        painter->drawConvexPolygon(pts);
    
        //绘制中心圆点
        radius = radius / 4;
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
    
        painter->restore();
    }
    
    void GaugeProgress::drawPointerIndicatorR(QPainter *painter)
    {
        if (!showPointer) {
            return;
        }
    
        int radius = radiusCircle - 15;
        painter->save();
    
        QPen pen;
        pen.setWidth(1);
        pen.setColor(progressColor);
        painter->setPen(pen);
        painter->setBrush(progressColor);
    
        QPolygon pts;
        pts.setPoints(3, -8, 0, 8, 0, 0, radius);
    
        painter->rotate(startAngle);
        double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (value - minValue);
        painter->rotate(degRotate);
        painter->drawConvexPolygon(pts);
    
        //增加绘制圆角直线,与之前三角形重叠,形成圆角指针
        pen.setCapStyle(Qt::RoundCap);
        pen.setWidthF(4);
        painter->setPen(pen);
        painter->drawLine(0, 0, 0, radius);
    
        //绘制中心圆点
        radius = radius / 4;
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
    
        painter->restore();
    }
    
    void GaugeProgress::drawPointerTriangle(QPainter *painter)
    {
        if (!showPointer) {
            return;
        }
    
        int radius = 20;
        int offset = radiusCircle - 25;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(progressColor);
    
        QPolygon pts;
        pts.setPoints(3, -radius / 2, offset, radius / 2, offset, 0, radius + offset);
    
        painter->rotate(startAngle);
        double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (value - minValue);
        painter->rotate(degRotate);
        painter->drawConvexPolygon(pts);
    
        painter->restore();
    }
    
    void GaugeProgress::drawValue(QPainter *painter)
    {
        if (!showValue) {
            return;
        }
    
        int radius = 100;
        painter->save();
        painter->setPen(textColor);
    
        QFont font;
        font.setPixelSize(showPointer ? radius - 50 : radius - 15);
        font.setBold(true);
        painter->setFont(font);
    
        QRectF textRect(-radius, -radius, radius * 2, radius * 2);
        QString strValue = QString("%1").arg((double)value, 0, 'f', precision);
        painter->drawText(textRect, Qt::AlignCenter, strValue);
        painter->restore();
    }
    
    

    控件介绍

    1. 超过140个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,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. 超过130个可见控件,6个不可见控件。
    8. 部分控件提供多种样式风格选择,多种指示器样式选择。
    9. 所有控件自适应窗体拉伸变化。
    10. 集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。
    11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。
    12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。
    13. 所有控件最后生成一个dll动态库文件,可以直接集成到qtcreator中拖曳设计使用。

    SDK下载

    • SDK下载链接:https://pan.baidu.com/s/1tD9v1YPfE2fgYoK6lqUr1Q 提取码:lyhk
    • 自定义控件+属性设计器欣赏:https://pan.baidu.com/s/1l6L3rKSiLu_uYi7lnL3ibQ 提取码:tmvl
    • 下载链接中包含了各个版本的动态库文件,所有控件的头文件,使用demo。
    • 自定义控件插件开放动态库dll使用(永久免费),无任何后门和限制,请放心使用。
    • 目前已提供22个版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
    • 不定期增加控件和完善控件,不定期更新SDK,欢迎各位提出建议,谢谢!
    • widget版本(QQ:517216493)qml版本(QQ:373955953)三峰驼(QQ:278969898)。

  • 相关阅读:
    iOS 新建xib文件时,最外层view的约束问题
    React native 无法弹出调试控件的问题
    从GitHub下载demo时遇到的依赖问题
    Mac 解决 Sourcetree 同步代码总需要密码的问题
    Mac 安装JRE 1.8
    正则表达式-- (.*?) 或 (.*+)
    字符串内有多个#号,每俩#号为一组,JavaScript 截取每组#号之间的字符
    Js/jQuery实时监听input输入框值变化
    Redis设置密码
    redis本机能访问 远程不能访问的问题
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/10793482.html
Copyright © 2020-2023  润新知