欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

漂亮的表盘(自绘)

程序员文章站 2022-05-28 14:37:10
...

先看效果
漂亮的表盘(自绘)

这次用了二种方式实现的。一种是利用QPainter直接绘制的,一种是利用QPainterPath实现的。
头文件代码

#ifndef QDIALCOMPWIDGET_H
#define QDIALCOMPWIDGET_H

#include <QWidget>
#include <QPainter>
#include <QConicalGradient>
#include "qmath.h"

#define  PI 3.12415926

//////////////////////////////////////////////////////////////////////////
//不支持指针颜色动态变化
//////////////////////////////////////////////////////////////////////////
class QDialCompWidget : public QWidget
{
    Q_OBJECT

public:
    QDialCompWidget(QWidget *parent = NULL);
    ~QDialCompWidget();

    void setMaxValue(qreal max);
    void setMinValue(qreal min);
    void setValue(qreal value);
    void setSuffix(QString sufstr); //后缀

private:
    inline void initdata();

protected:
    void paintEvent(QPaintEvent *e);
    void drawRoundByPath(QPainter &painter);    //利用QPainterPath 实现
    void drawRoundByPainter(QPainter &painter); //利用QPainter实现

private:
    QString m_sufstr;
    qreal m_max;
    qreal m_min;
    qreal m_value;
    QBrush m_oldbrush;


};

#endif // QDIALCOMPWIDGET_H

Cpp文件代码

#include "qdialcompwidget.h"

QDialCompWidget::QDialCompWidget(QWidget *parent)
    : QWidget(parent)
{
    initdata();
}

QDialCompWidget::~QDialCompWidget()
{

}

void QDialCompWidget::initdata()
{
    m_max = 100;
    m_min = 0;
    m_value = 0;
}
void QDialCompWidget::setMaxValue( qreal max )
{
    m_max = max;
    update();
}

void QDialCompWidget::setMinValue( qreal min )
{
    m_min = min;
    update();
}

void QDialCompWidget::setValue( qreal value )
{
    m_value = value;
    update();

}

void QDialCompWidget::setSuffix( QString sufstr )
{
    m_sufstr = sufstr;
    update();
}

void QDialCompWidget::paintEvent( QPaintEvent *e )
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::NoPen);
    m_oldbrush = painter.background();
    //drawRoundByPainter(painter);
    drawRoundByPath(painter);
}

void QDialCompWidget::drawRoundByPainter( QPainter &painter )
{
    int w = width();
    int h = height();
    qreal randius= qMin(w*0.8/2,h*0.8/2);
    int setp = randius*0.08;
    qreal outrandius = randius + setp;
    qreal inrandius = randius - setp;

    QPointF certp(w/2,h/2);
    qreal startAngle = -60*16;
    qreal spanAngle = 300*16;
    qreal angele = 30;
    qreal lw,lh;
    lw = outrandius*qSin(PI/6);
    lh = outrandius*qCos(PI/6);

    QPointF outleftp(certp.x()-lw,certp.y()+lh);
    QPointF outrigth(certp.x()+lw,certp.y()+lh);
    QRectF outrectangle(certp.x()-outrandius, certp.y()-outrandius, outrandius*2, outrandius*2);

    //背景色
    painter.save();
    painter.setBrush(m_oldbrush);
    painter.drawEllipse(outrectangle);
    painter.restore();

    //外圆
    painter.save();
    QConicalGradient congradient(outrectangle.center(),245);
    congradient.setColorAt(0,QColor("#EC0000")); //红色
    congradient.setColorAt(0.5,QColor("#E5D317"));
    congradient.setColorAt(1,QColor("#2BB52C"));   //绿色
    painter.setBrush(congradient);
    painter.drawPie(outrectangle, startAngle, spanAngle);
    painter.restore();


    //内圆
    lw = inrandius*qSin(PI/6);
    lh = inrandius*qCos(PI/6);

    QPointF inleftp(certp.x()-lw,certp.y()+lh);
    QPointF inrigth(certp.x()+lw,certp.y()+lh);

    painter.save();
    QRectF inrectangle(certp.x()-inrandius, certp.y()-inrandius, inrandius*2, inrandius*2);
    painter.drawPie(inrectangle,startAngle,spanAngle);
    painter.restore();

    painter.save();
    painter.setBrush(congradient);
    //左侧半小圆
    qreal tmph =(outleftp.y()-inleftp.y())/2;
    qreal tmpw =(outleftp.x()-inleftp.x())/2;

    QPointF tp(outleftp.x()-tmpw,outleftp.y()-tmph);
    QRectF rmprect(tp.x()-setp,tp.y()-setp,setp*2,setp*2);
    painter.drawChord(rmprect,-130*16,200*16);  //角度大小取决于 angele ,跨度200级以上(防止放大有小白条)

    //右侧半小圆
    tmph =(outrigth.y()-inrigth.y())/2;
    tmpw =(outrigth.x()-inrigth.x())/2;

    QPointF righttp(outrigth.x()-tmpw,outrigth.y()-tmph);
    QRectF rmrightrect(righttp.x()-setp,righttp.y()-setp,setp*2,setp*2);
    painter.drawChord(rmrightrect,110*16,200*16); //角度大小取决于 angele,跨度200级以上(防止放大有小白条)
    painter.restore();

    //中间部分 白色填充
    painter.save();
    painter.setBrush(/*Qt::white*/m_oldbrush);
    painter.drawEllipse(inrectangle);
    painter.restore();

    //里侧圆
    painter.save();
    qreal inirandius = inrandius*0.9;
    QPainterPath path;
    QRectF inirect(certp.x()-inirandius,certp.y()-inirandius,inirandius*2,inirandius*2);

    QRadialGradient radialgradient(inirect.center(),inirandius);
    QColor color_1("#2BB52C"); //绿色
    QColor color_2("#2BB52C");
    QColor color_3("#2BB52C");
    color_1.setAlpha(200);
    color_2.setAlpha(100);
    color_3.setAlpha(20);
    radialgradient.setColorAt(0.95,color_1); //
    radialgradient.setColorAt(0.99,color_2);
    radialgradient.setColorAt(1,color_3);   
    painter.setBrush(radialgradient);

    path.addEllipse(inirect);

    painter.drawPath(path);
    painter.restore();
    painter.save();
    painter.setBrush(/*Qt::white*/m_oldbrush);
    inirandius *= 0.97;
    QRectF tmprect(certp.x()-inirandius,certp.y()-inirandius,inirandius*2,inirandius*2);
    painter.drawEllipse(tmprect);
    painter.restore();

    //值value
    painter.save();
    QPen textpen;
    textpen.setColor("black");
    QFont f;
    f.setPixelSize(inirandius/2);
    painter.setPen(textpen);
    painter.setFont(f);
    painter.drawText(tmprect,Qt::AlignCenter,QString("%1%2").arg(m_value).arg(m_sufstr));
    painter.restore();

    //最大最小值
    painter.save();
    QFont f2;
    f2.setPixelSize(inirandius/4);
    painter.setPen(textpen);
    painter.setFont(f2);
    QRectF minrect(outleftp.x(),h*0.9,randius,randius*0.2);
    QRectF maxrect(certp.x()+inirandius/2,h*0.9,randius,randius*0.2);
    painter.drawText(minrect,QString("%1").arg(m_min));
    painter.drawText(maxrect,QString("%1").arg(m_max));
    painter.restore();

    //指针
    setp = 30+1.0*m_value*(360-55)/(m_max-m_min);   //占用300度不是360 
    painter.save();
    QTransform t;
    t.translate(certp.x(),certp.y());
    t.rotate(setp);
    painter.setTransform(t);

    //QRectF rectcongradient2(-inirandius,-inirandius,inirandius*2,inirandius*2);
    //QConicalGradient congradient2(rectcongradient2.center(),360);
    ////congradient2.setAngle(-240+setp-30);
    //congradient2.setColorAt(0,QColor("#EC0000")); //红色
    //congradient2.setColorAt(0.5,QColor("#E5D317"));
    //congradient2.setColorAt(1.0,QColor("#2BB52C"));   //绿色
    //painter.setBrush(congradient2);

    QRectF maxrect22(0,inirandius*0.88,5,inirandius*0.1);
    painter.setBrush(/*Qt::red*/congradient);
    painter.drawRoundedRect(maxrect22,5,5);
    painter.restore();

}

void QDialCompWidget::drawRoundByPath( QPainter &painter )
{
    int w = width();
    int h = height();
    qreal randius= qMin(w*0.8/2,h*0.8/2);
    int setp = randius*0.08;
    qreal outrandius = randius + setp;
    qreal inrandius = randius - setp;

    QPointF certp(w/2,h/2);

    qreal startAngle = -60;
    qreal spanAngle = 300;
    qreal angele = 30;

    painter.save();
    //内圆
    qreal lw = inrandius*qSin(PI/6);
    qreal lh = inrandius*qCos(PI/6);

    QPointF inleftp(certp.x()-lw,certp.y()+lh);
    QPointF inrigth(certp.x()+lw,certp.y()+lh);

    QRectF rectangle(certp.x()-inrandius, certp.y()-inrandius, inrandius*2, inrandius*2);
    QPainterPath path;
    path.moveTo(inleftp);

    path.arcTo(rectangle, startAngle, spanAngle);

    //外圆
    lw = outrandius*qSin(PI/6);
    lh = outrandius*qCos(PI/6);

    QPointF outleftp(certp.x()-lw,certp.y()+lh);
    QPointF outrigth(certp.x()+lw,certp.y()+lh);
    path.moveTo(outleftp);

    QRectF rectangle2(certp.x()-outrandius, certp.y()-outrandius, outrandius*2, outrandius*2);
    path.arcTo(rectangle2, startAngle, spanAngle);


    QConicalGradient congradient(rectangle2.center(),250);
    congradient.setColorAt(0,QColor("#EC0000")); //红色
    congradient.setColorAt(0.5,QColor("#E5D317"));
    congradient.setColorAt(1,QColor("#2BB52C"));   //绿色
    painter.setBrush(congradient);
    painter.drawPath(path);
    painter.eraseRect(inleftp.x(),inleftp.y()-1,inrigth.x()-inleftp.x(),outleftp.y()-inleftp.y()+20);

    QPainterPath leftpath;
    //左侧小圆
    leftpath.moveTo(outleftp);
    qreal tmph =(outleftp.y()-inleftp.y())/2;
    qreal tmpw =(outleftp.x()-inleftp.x())/2;

    QPointF tp(outleftp.x()-tmpw,outleftp.y()-tmph);
    QRectF rmprect(tp.x()-setp,tp.y()-setp,setp*2,setp*2);
    leftpath.arcTo(rmprect,-110,200);  //角度大小取决于 angele
    //painter.setBrush(congradient);
    painter.drawPath(leftpath);

    QPainterPath rightpath;
    //右侧小圆
    rightpath.moveTo(outrigth);
    tmph =(outrigth.y()-inrigth.y())/2;
    tmpw =(outrigth.x()-inrigth.x())/2;

    QPointF righttp(outrigth.x()-tmpw,outrigth.y()-tmph);
    QRectF rmrightrect(righttp.x()-setp,righttp.y()-setp,setp*2,setp*2);
    rightpath.arcTo(rmrightrect,110,200); //角度大小取决于 angele
    //painter.setBrush(congradient);
    painter.drawPath(rightpath);
    painter.restore();


    //中间部分 白色填充
    painter.save();
    painter.setBrush(/*Qt::white*/m_oldbrush);
    painter.drawEllipse(rectangle);
    painter.restore();

    //里侧圆
    painter.save();
    qreal inirandius = inrandius*0.9;
    QPainterPath inipath;
    QRectF inirect(certp.x()-inirandius,certp.y()-inirandius,inirandius*2,inirandius*2);

    QRadialGradient radialgradient(inirect.center(),inirandius);
    QColor color_1("#2BB52C"); //绿色
    QColor color_2("#2BB52C");
    QColor color_3("#2BB52C");
    color_1.setAlpha(200);
    color_2.setAlpha(100);
    color_3.setAlpha(20);
    radialgradient.setColorAt(0.95,color_1); //
    radialgradient.setColorAt(0.99,color_2);
    radialgradient.setColorAt(1,color_3);   
    painter.setBrush(radialgradient);

    inipath.addEllipse(inirect);

    painter.drawPath(inipath);
    painter.restore();
    painter.save();
    painter.setBrush(/*Qt::white*/m_oldbrush);
    inirandius *= 0.97;
    QRectF tmprect(certp.x()-inirandius,certp.y()-inirandius,inirandius*2,inirandius*2);
    painter.drawEllipse(tmprect);
    painter.restore();

    //值value
    painter.save();
    QPen textpen;
    textpen.setColor("black");
    QFont f;
    f.setPixelSize(inirandius/2);
    painter.setPen(textpen);
    painter.setFont(f);
    painter.drawText(tmprect,Qt::AlignCenter,QString("%1%2").arg(m_value).arg(m_sufstr));
    painter.restore();

    //最大最小值
    painter.save();
    QFont f2;
    f2.setPixelSize(inirandius/4);
    painter.setPen(textpen);
    painter.setFont(f2);
    QRectF minrect(outleftp.x(),h*0.9,randius,randius*0.2);
    QRectF maxrect(certp.x()+inirandius/2,h*0.9,randius,randius*0.2);
    painter.drawText(minrect,QString("%1").arg(m_min));
    painter.drawText(maxrect,QString("%1").arg(m_max));
    painter.restore();

    //指针
    setp = 30+1.0*m_value*(360-60)/(m_max-m_min);   //占用300度不是360 
    painter.save();
    QTransform t;
    t.translate(certp.x(),certp.y());
    t.rotate(setp);
    painter.setTransform(t);


    QRectF maxrect22(0,inirandius*0.88,5,inirandius*0.1);
    painter.setBrush(/*Qt::red*/congradient);
    painter.drawRoundedRect(maxrect22,5,5);
    painter.restore();
}