博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
32.QT-制作最强电压电阻表盘,可以自定义阴影效果,渐变颜色,图标,文字标签等-附带demo程序...
阅读量:7261 次
发布时间:2019-06-29

本文共 7850 字,大约阅读时间需要 26 分钟。

由于上位机需要绘制电压电阻表盘,如下图所示:

后来,在网上找阿找,还是没找到满意的,索性自己来画控件算了,由于第一次画控件,所以花了我2天时间,才画好

效果图如下:

上图的所有颜色(包括滑动的渐变/单一颜色,以及字体颜色)都可以自定义,包括图标也可以(上面的电阻图标,网上没找到好看的,所以很丑~)

整体效果图如下所示:

 该demo程序放在了提供的源码地址里了,下载好后,在子文件夹demo1里面

介绍

代码里添加了自适应设置,根据窗口大小自动改变标签,图标,刻度值,中心圆数值等

代码里集成了定时器,可以通过setTimerType(int msec,int v)成员函数实现表盘指针旋转快慢,每过多少msec,跑多少值(v),如果msec=0或者v=0,则表示不用定时器,直接跳到终点。

代码里通过setGradientColorMode(QList<QColor>& Qcolors)成员函数可以自定义一组渐变颜色.

也可以通过setSingleColorMode(QColor color)成员函数自定义单一颜色(上图2就是设置的单一颜色).

 

代码介绍

1.代码里通过 painter类来绘图,其中paintEvent()函数如下所示

void Dial::paintEvent(QPaintEvent *){    QPainter painter(this);    painter.setPen(Qt::NoPen);    painter.setRenderHint(QPainter::Antialiasing,true);    painter.setRenderHint(QPainter::SmoothPixmapTransform);    painter.translate(width()/2,height()/2);    radius = qMin(width(),height())/2;    centerR=radius*0.4;       //设置中心圆大小    drawObkColor(painter);           //外圆盘    drawScalebkColor(painter);      //画刻度圆    drawslideScaleColor(painter);   //画划过的颜色    drawShade(painter);            //画阴影    drawScaleColor(painter);    drawbkColor(painter);          //画内圆    drawScaleTextColor(painter);   //画刻度值    drawPointColor(painter);    drawCenterColor(painter);      //绘制中心圆    drawIconValueColor(painter);    drawlabelColor(painter);}

2.然后进入drawObkColor()函数,来绘画外圆盘,函数如下所示

void Dial::drawObkColor(QPainter& paint)      //绘制外圆{        paint.save();        QConicalGradient  Conical(0,0,90);        Conical.setColorAt(0,oobkColor);        Conical.setColorAt(0.5,oobkColor);        Conical.setColorAt(0.12,oobkColor.darker(40));        Conical.setColorAt(0.88,oobkColor.darker(40));        Conical.setColorAt(0.4,oobkColor.darker(30));        Conical.setColorAt(0.6,oobkColor.darker(30));        Conical.setColorAt(0.25,oobkColor.darker(160));        Conical.setColorAt(0.75,oobkColor.darker(160));        Conical.setColorAt(1,oobkColor);        paint.setBrush(Conical);        paint.drawEllipse(QPointF(0,0), radius*0.96,radius*0.98);        Conical.setAngle(270);        Conical.setColorAt(0,obkColor.darker(40));        Conical.setColorAt(0.5,obkColor.darker(40));        Conical.setColorAt(0.25,obkColor.darker(160));        Conical.setColorAt(0.75,obkColor.darker(160));        paint.setBrush(Conical);        paint.drawEllipse(QPointF(0,0), radius*0.93,radius*0.94);        paint.restore();}

外圆盘效果如下所示:

3.然后接下来开始画刻度圆,画了它后,才能开始画刻度和划过的颜色等

void Dial::drawScalebkColor(QPainter &paint)        //绘制刻度圆{    paint.save();    paint.setBrush(bkColor);    paint.drawEllipse(QPointF(0,0), radius*0.90,radius*0.90);    paint.restore();}

4.然后接下来开始画划过的颜色,就是上图指针划过后都会带有颜色的那种 (以单色颜色为例)

void Dial::drawslideScaleColor(QPainter &paint)    //画划过的颜色{    /*单一颜色*/      int Star_Angle= 210*16-(int)((value/(maxvalue-minvalue))*240*16);    int spanAngle  =  210*16 - Star_Angle;    if(spanAngle==0)        return ;    qreal SlideBottom =  ((qreal)radius*0.77)/((qreal)radius*0.90);        qreal SlideCenterTop = 1-(1-SlideBottom)/3;                            qreal SlideCenterBottom = SlideBottom+(1-SlideBottom)/3+0.01;          paint.save();    QColor Tint_SlideColor = SingleSlideColor;    QRadialGradient Radial(0,0,radius*0.90);    Tint_SlideColor.setAlpha(40);    Radial.setColorAt(1,Tint_SlideColor);    Radial.setColorAt(SlideBottom-0.005,Tint_SlideColor);    Radial.setColorAt(0,Qt::transparent);    Radial.setColorAt(SlideBottom-0.006,Qt::transparent);    Tint_SlideColor = SingleSlideColor;    Tint_SlideColor.setAlpha(50);    Radial.setColorAt(SlideCenterBottom-0.03,Tint_SlideColor);    Radial.setColorAt(SlideCenterTop+0.03,Tint_SlideColor);    Tint_SlideColor = SingleSlideColor;    Tint_SlideColor.setAlpha(50);    Radial.setColorAt(SlideCenterBottom-0.01,SingleSlideColor.darker(200));    Radial.setColorAt(SlideCenterTop+0.01,SingleSlideColor.darker(200));    Radial.setColorAt(SlideCenterBottom,SingleSlideColor);    Radial.setColorAt(SlideCenterTop,SingleSlideColor);    paint.setPen(Qt::NoPen);    paint.setBrush(Radial);    paint.drawPie(QRectF((qreal)-radius*0.90,(qreal)-radius*0.90,(qreal)radius*1.80,(qreal)radius*1.80),Star_Angle,spanAngle);    paint.restore();   //... ...     }

效果:

5.然后接下来便开始画刻度和刻度值,其中比较重要的就是绘制刻度值

由于Painter的rotate()旋转文字时,也会将文字倾斜了,所以我们需要自定义rotate()函数

具体参考我另一篇rotate函数分析:    

 

drawScaleTextColor()画刻度值函数如下所示:

void Dial::drawScaleTextColor(QPainter &paint)    //绘制刻度值{    /*绘制文字刻度*/    paint.save();    paint.setPen(ScaleColor);    QString text("%1");    int size;           //动态计算文字大小    if(radius<=120)       size = 10;    else if((radius>120)&&(radius<500))       size = 13+(radius-120)/30;    else if(radius>=500)       size = 13+(radius-120)/40;    paint.setFont(QFont("Euphemia",size,QFont::DemiBold));    QPoint TextPoint(0,radius*0.77-size*0.9);        //设置90°的文字    TextPoint = CustomRotate(TextPoint,90,240);   //获取点=210°的文字位置    qreal TextRotate=210;     for(int i=0;i<7;i++)              //设置7个刻度值    {              //... ...          qreal Current_Value =(qreal)i*((maxvalue-minvalue)/6);          if((Current_Value>value&&(paint.pen().color()!=ScaleColor)))          {              paint.setPen(ScaleColor);          }          else if((Current_Value<=value&&(paint.pen().color()!=slideScaleColor)))          {              paint.setPen(slideScaleColor);          }       paint.drawText(QRect(TextPoint.x()-size*1.5+offest[i].x(),TextPoint.y()-size*1.2+offest[i].y(),size*3,size*2.4),alingns[i],text.arg((maxvalue-minvalue)*i/6));       TextPoint = CustomRotate(TextPoint,TextRotate,40);   //获取点=210°的文字位置       TextRotate-=40;    }    paint.restore();}

效果如下所示:

 6.然后接下来开始画指针

void Dial::drawPointColor(QPainter &paint)          //绘制指针{    qreal PointTop;                //动态计算指针头    qreal PointBottom;             //动态计算指针底部    if(radius<=120)    {        PointTop = 2;        PointBottom = 6;    }    else if((radius>120)&&(radius<500))    {        PointTop = 2 + (radius-120)/100;        PointBottom = PointTop*3;    }    else if(radius>=500)    {        PointTop = 2 + (radius-120)/140;        PointBottom = PointTop*3;    }    //指针    const QPointF  Pointer[4] = {        QPointF(- PointTop / 2, radius*0.80),        QPointF(PointTop / 2, radius*0.80),        QPointF(PointBottom / 2, centerR*0.9),        QPointF(-PointBottom / 2, centerR*0.9)    };    paint.save();    paint.setBrush(PointerColor);    paint.setPen(PointerColor.darker(300));    qreal Current_Angle =60+(int)((value/(maxvalue-minvalue))*240);    paint.rotate(Current_Angle);    paint.drawConvexPolygon(Pointer, 4);    paint.restore();}

效果如下:

7.然后继续画中心圆

void Dial::drawCenterColor(QPainter &paint)      //绘制中心圆{    paint.save();    QRadialGradient Radial(0,0,centerR,0,0);    Radial.setColorAt(1,centercolor.lighter(170));    Radial.setColorAt(0.98,centercolor.lighter(150));    Radial.setColorAt(0.95,centercolor.lighter(130));    Radial.setColorAt(0.70,centercolor);    paint.setBrush(Radial);    paint.drawEllipse(QPointF(0,0), centerR,centerR);    paint.restore();}

效果如下:

  

剩下的代码就是画标签和值还有图标啦,由于渐变代码多一些,所以具体参考可以去下载源代码.在最下面有下载地址

 

 

 


2018-06-30    第二次更新

内容

  • 支持负数到正数刻度值显示
  • 支持小数点位数设置
  • 优化刻度值自适应窗口,能具体显示个位至千位
  • 支持表盘所有颜色搭配 
  • 添加arriveEnd()信号函数

并写了个demo测试程序,可以直接测试数据,demo程序效果图如下所示:

该demo程序放在了提供的源码地址里了,下载好后,在文件夹demo2里面

 

 测试图1-设置颜色(任意搭配颜色):

 

测试图2-设置正负数值:

 

 

 

 


2018-07-01    第三次更新

  •  在上个更新里,添加了表盘阴影效果,来实现立体感

如下图的第二个表盘所示:

 

该demo程序放在了提供的源码地址里了,下载好后,在文件夹demo3里面

 

主要内容:

  添加了一个drawDialShade(QPainter &paint,qreal Angle_start,qreal Angle_end,qreal ratio,int alpha)成员函数,来绘制白色阴影,实现的光影效果.

该函数的参数含义如下所示:

  • Angle_start Angle_end :表示圆盘的起始/结束角度,Angle_end必须大于Angle_start哦
  • ratio:表示绘制的阴影亮度的扁与平(为0~1之间),为0表示平的圆环,为0.99表示最扁的圆环,大于等于1则不会绘制
  • alpha:表示铺上的白色透明度,0表示透明,255表示不透明

 

如果觉得上图的阴影效果觉得不合适,可以自己修改哦~

 

drawDialShade()函数使用示例:

1.单独调用drawDialShade(painter,30,180,0,255)时

含义:  表示在内圆盘上的30°~180°之间绘制圆月,ratio=0,所以圆月是平的,alpha=255,表示不透明

效果如下:

2.单独调用drawDialShade(painter,45,180,0.5,150)时

含义:  表示在内圆盘上的45°~180°之间绘制圆月,圆月是半扁的,半透明

效果如下:

 

PS:要实现更强的立体感,多次调用改参数即可

 

 

上面所有源码已放在源代码下载地址里了,具体源代码下载地址为: 

 

如果觉得不错,点个赞呗~

 

转载地址:http://clddm.baihongyu.com/

你可能感兴趣的文章
世界那么大,我们一起到处去看看
查看>>
从大起到大落 各国的虚拟货币市场有何转变?
查看>>
新西兰天维网:新西兰净移民数量呈下降趋势
查看>>
婴儿患小儿脐疝肚子鼓起 父亲竟一刀划开肚脐“放气”
查看>>
英首相提交“脱欧”替代方案 重申不寻求二次公投
查看>>
不放弃!西班牙两岁男童落井8天 救援队仍钻井营救
查看>>
兰州火车站扩能改造完成 正式投入使用
查看>>
宁夏首票关税保证保险报关单顺利通关
查看>>
贷款增速达12.6% 银行业服务实体经济能力提升
查看>>
南方持续强降雪 京广高铁部分列车晚点1到3小时
查看>>
阿里程序员吐槽:玩命赚钱依旧抵不过拆迁户,奋斗的意义呢
查看>>
「算法」如何实现大整数相乘?(下)
查看>>
Oracle总结【SQL细节、多表查询、分组查询、分页】
查看>>
具有代表性的 HTTP 状态码
查看>>
iOS 组件化 —— 路由设计思路分析
查看>>
扯扯ID
查看>>
mp-redux:解耦小程序中的业务与视图,让测试更容易
查看>>
Sql注入
查看>>
如何用Python写一个贪吃蛇AI
查看>>
Docker 镜像优化与最佳实践
查看>>