Qt自定义控件仪表盘

核心代码来自   feiyangqingyun 大神链接:https://blog.csdn.net/feiyangqingyun/article/details/89428878

 

#ifndef DASHBOARD_H
#define DASHBOARD_H

#include <QWidget>
#include <QColor>
#include <QTimer>
#include <QFont>

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 Dashboard : 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 Dashboard(QWidget *parent = 0);
    ~Dashboard();

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 = -5;                //最小值
    double maxValue = 5;                //最大值
    double value = 0;                   //目标值
    int precision = 2;                  //精确度,小数点后几位

    int scaleMajor = 10;                 //大刻度数量
    int scaleMinor = 5;                 //小刻度数量
    int startAngle = 45;                 //开始旋转角度
    int endAngle = 45;                   //结束旋转角度

    bool animation = 0;                 //是否启用动画显示
    double animationStep = 1;           //动画显示时步长

    int ringWidth = 7;                  //圆环宽度
    int ringStartPercent=10;           //第一圆环比例
    int ringMidLeftPercent=10;
    int ringMidPercent=60;             //第二圆环比例
    int ringMidRightPercent=10;
    int ringEndPercent=10;             //第三圆环比例

    QColor ringColorStart= QColor(255,0,0,255);          //第一圆环颜色
    QColor ringColorMidLeft = QColor(250,211,0,144);
    QColor ringColorMid = QColor(0,255,0,255);            //第二圆环颜色
    QColor ringColorMidRight = QColor(250,211,0,144);
    QColor ringColorEnd = QColor(255,0,0,255);            //第三圆环颜色

    QColor pointerColor = Qt::red;            //指针颜色
    QColor textColor = Qt::red;//Qt::darkGreen;               //文字颜色

    bool reverse;                   //是否往回走
    double currentValue = 0;            //当前值
    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 setValue(const QString &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 // DASHBOARD_H
#include "dashboard.h"
#include <QPainter>
#include <QDebug>
#include <QtMath>
Dashboard::Dashboard(QWidget *parent) : QWidget(parent)
{
    if(this->animation == true)
    {
        QTimer::singleShot(50, this, SLOT(updateValue()));
    }
}
Dashboard::~Dashboard()
{

}
void Dashboard::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); /* 比例缩放 */

    drawRing(&painter);
    drawScale(&painter);
    drawScaleNum(&painter);
    drawPointer(&painter);
    drawValue(&painter);
}

void Dashboard::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 angleMidLeft = angleAll * (double)ringMidLeftPercent / 100;
    double angleMid = angleAll * (double)ringMidPercent / 100;
    double angleMidRight = angleAll * (double)ringMidRightPercent / 100;
    double angleEnd = angleAll * (double)ringEndPercent / 100;

    //绘制第一圆环
    pen.setColor(ringColorStart);
    painter->setPen(pen);
    painter->drawArc(rect, (270 - startAngle - angleStart) * 16, angleStart * 16);

    pen.setColor(ringColorMidLeft);
    painter->setPen(pen);
    painter->drawArc(rect, (270 - startAngle - angleStart - angleMidLeft) * 16, angleMidLeft * 16);

    //绘制第二圆环
    pen.setColor(ringColorMid);
    painter->setPen(pen);
    painter->drawArc(rect, (270 - startAngle - angleStart - angleMidLeft- angleMid) * 16, angleMid * 16);

    pen.setColor(ringColorMidRight);
    painter->setPen(pen);
    painter->drawArc(rect, (270 - startAngle - angleStart - angleMidLeft- angleMid - angleMidRight) * 16, angleMidRight * 16);

    //绘制第三圆环
    pen.setColor(ringColorEnd);
    painter->setPen(pen);
    painter->drawArc(rect, (270 - startAngle - angleStart - angleMidLeft - angleMid -angleMidRight - angleEnd) * 16, angleEnd * 16);

    painter->restore();
}

void Dashboard::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 indexMidLeft = steps * (double)ringMidLeftPercent / 100 - 1;
    int indexMid = steps * (double)ringMidPercent / 100 - 1;
    int indexMidRight = steps * (double)ringMidRightPercent / 100 - 1;
    int indexEnd = steps * (double)ringEndPercent / 100 + 1;
    int index = 0;
    //qDebug("drawScale index=%d indexStart=%d", index, indexStart);
    for (int i = 0; i <= steps; i++) {
        //if (i % scaleMinor == 0) {
            //根据所在圆环范围切换颜色
            if (index < indexStart) {
                pen.setColor(ringColorStart);
            } else if (index < (indexStart + indexMidLeft+1)) {
               pen.setColor(ringColorMidLeft);
            }
            else if (index < (indexStart + indexMid + indexMidLeft+1)) {
                pen.setColor(ringColorMid);
            }
            else if (index <= (indexStart + indexMid + indexMidLeft + indexMidRight + 1)) {
                pen.setColor(ringColorMidRight);
            }
            else if (index < (indexStart + indexMid + indexMidLeft + indexMidRight + indexEnd)) {
                pen.setColor(ringColorEnd);
            }

            index++;
       if (i % scaleMinor == 0){
            pen.setWidthF(0.5); //1.5
            painter->setPen(pen);
            painter->drawLine(0, radius - 5 - ringWidth, 0, radius - ringWidth+1);
        } else {
            pen.setWidthF(0.5);
            painter->setPen(pen);
            painter->drawLine(0, radius - 3 - ringWidth, 0, radius - ringWidth+1);
        }

        painter->rotate(angleStep);
    }

    painter->restore();
}

void Dashboard::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;
        if(value >= -3.00 && value <= 3.00)
            painter->setPen(ringColorMid);
        else {
            painter->setPen(textColor);
        }
        QString strValue = QString("%1").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 Dashboard::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);
    if(maxValue < currentValue)
        currentValue = maxValue;
    else  if(minValue > currentValue)
        currentValue = minValue;

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

    painter->restore();
}

void Dashboard::drawValue(QPainter *painter)
{
    int radius = 100;
    painter->save();
    painter->setPen(textColor);
    //painter->setBrush(QColor(255,0,0,255));
    QFont font;
    font.setPixelSize(12);
    font.setFamily("微软雅黑");
    painter->setFont(font);

    // QRectF textRect(-radius, radius / 2, radius * 2, radius / 3);
    QRectF textRect(-radius/4, radius / 4, radius/4*2, radius / 4);
    painter->drawRect(textRect); //增加一个矩形框
    painter->setPen(Qt::black);
    QString strValue = QString("%1").arg((double)currentValue, 0, 'f', precision);
    painter->drawText(textRect, Qt::AlignCenter, strValue);

    painter->setPen(textColor);
    QRectF text(-radius/2, -radius / 2, radius, radius / 4);
    //painter->drawRect(text); //增加一个矩形框
    QString textValue="差分张力(KN)";
    painter->drawText(text, Qt::AlignCenter, textValue);

    painter->restore();
}
double Dashboard::getMinValue()const
{
    return this->minValue;
}
double Dashboard::getMaxValue()const
{
    return this->maxValue;
}
double Dashboard::getValue()const
{
    return this->currentValue;
}
int Dashboard::getPrecision()const
{
    return this->precision;
}
int Dashboard::getScaleMajor()const
{
    return this->scaleMajor;
}
int Dashboard::getScaleMinor()const
{
    return this->scaleMinor;
}
int Dashboard::getStartAngle()const
{
    return this->startAngle;
}
int Dashboard::getEndAngle()const
{
    return this->endAngle;
}
bool Dashboard::getAnimation()const
{
    return this->animation;
}
double Dashboard::getAnimationStep()const
{
    return this->animationStep;
}
int Dashboard::getRingWidth()const
{
    return  this->ringWidth;
}
int Dashboard::getRingStartPercent()const
{
    return this->ringStartPercent;
}
int Dashboard::getRingMidPercent()const
{
    return this->ringMidPercent;
}
int Dashboard::getRingEndPercent()const
{
    return  this->ringEndPercent;
}
QColor Dashboard::getRingColorStart()      const
{
    return this->ringColorStart;
}
QColor Dashboard::getRingColorMid()        const
{
    return this->ringColorMid;
}
QColor Dashboard::getRingColorEnd()        const
{
    return this->ringColorEnd;
}
QColor Dashboard::getPointerColor()        const
{
    return this->pointerColor;
}
QColor Dashboard::getTextColor()           const
{
    return this->textColor;
}

QSize Dashboard::sizeHint()const
{
    int width = this->width();
    int height = this->height();

    return QSize(qMin(width, height), qMin(width, height));
}
QSize Dashboard::minimumSizeHint()const
{
    int width = this->width();
    int height = this->height();

    return QSize(qMin(width, height), qMin(width, height));
}

void Dashboard::setRange(double minValue, double maxValue)
{
    this->minValue = minValue;
    this->maxValue = maxValue;
}
void Dashboard::setRange(int minValue, int maxValue)
{
    this->minValue = minValue;
    this->maxValue = maxValue;
}
//设置最大最小值
void Dashboard::setMinValue(double minValue)
{
    this->minValue = minValue;
}
void Dashboard::setMaxValue(double maxValue)
{
    this->maxValue = maxValue;
}

//设置目标值
void Dashboard::setValue(double value)
{
    this->value = value;
    if(this->animation == true)
    {
        QTimer::singleShot(5, this, SLOT(updateValue()));
    }
    else {
        this->currentValue = this->value;
    }
    update();
}
void Dashboard::setValue(int value)
{
    this->value =value;
    if(this->animation == true)
    {
        QTimer::singleShot(5, this, SLOT(updateValue()));
    }
    else {
        this->currentValue = this->value;
    }
    update();
}
void Dashboard::setValue(const QString &value)
{
    this->value = value.toDouble();
    if(this->animation == true)
    {
        QTimer::singleShot(5, this, SLOT(updateValue()));
    }
    else {
        this->currentValue = this->value;
    }
    update();
}

//设置精确度
void Dashboard::setPrecision(int precision)
{
    this->precision = precision;
}
//设置主刻度数量
void Dashboard::setScaleMajor(int scaleMajor)
{
    this->scaleMajor = scaleMajor;
}
//设置小刻度数量
void Dashboard::setScaleMinor(int scaleMinor)
{
    this->scaleMinor = scaleMinor;
}
//设置开始旋转角度
void Dashboard::setStartAngle(int startAngle)
{
    this->startAngle = startAngle;
}
//设置结束旋转角度
void Dashboard::setEndAngle(int endAngle)
{
    this->endAngle = endAngle;
}

//设置是否启用动画显示
void Dashboard::setAnimation(bool animation)
{
    this->animation = animation;
    if(this->animation == true)
    {
        QTimer::singleShot(5, this, SLOT(updateValue()));
    }
}
//设置动画显示的步长
void Dashboard::setAnimationStep(double animationStep)
{
    this->animationStep = animationStep;
}
void Dashboard::setRingWidth(int ringWidth)
{
    this->ringWidth = ringWidth;
}

//设置三个圆环所占比例
void Dashboard::setRingStartPercent(int ringStartPercent)
{
    this->ringStartPercent = ringStartPercent;
}
void Dashboard::setRingMidPercent(int ringMidPercent)
{
    this->ringMidPercent = ringMidPercent;
}
void Dashboard::setRingEndPercent(int ringEndPercent)
{
    this->ringEndPercent = ringEndPercent;
}

//设置三个圆环颜色
void Dashboard::setRingColorStart(const QColor &ringColorStart)
{
    this->ringColorStart = ringColorStart;
}
void Dashboard::setRingColorMid(const QColor &ringColorMid)
{
    this->ringColorMid = ringColorMid;
}
void Dashboard::setRingColorEnd(const QColor &ringColorEnd)
{
    this->ringColorEnd = ringColorEnd;
}

//设置指针颜色
void Dashboard::setPointerColor(const QColor &pointerColor)
{
    this->pointerColor = pointerColor;
}
//设置文本颜色
void Dashboard::setTextColor(const QColor &textColor)
{
    this->textColor = textColor;
}
void Dashboard::updateValue()
{
    if(this->animation == true)
    {
        if(fabs(currentValue - value) > 0.001)
        {
            if(currentValue - value > 0.001)
                currentValue = currentValue - animationStep;
            else {
                currentValue = currentValue + animationStep;
            }
            QTimer::singleShot(5, this, SLOT(updateValue()));
            update();
        }
    }
}

 

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值