由於上位機需要繪制電壓電阻表盤,如下圖所示:
后來,在網上找阿找,還是沒找到滿意的,索性自己來畫控件算了,由於第一次畫控件,所以花了我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函數分析: 31.QPainter-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:要實現更強的立體感,多次調用改參數即可
上面所有源碼已放在源代碼下載地址里了,具體源代碼下載地址為:
https://download.csdn.net/download/qq_37997682/10512710
2019-05-29 (QT5版本更新)
- 由於之前上傳的表盤是QT4版本 編碼為GBK的,對有些只學過QT5的同學們不好移植,所以從新上傳一個QT5版本的,編碼格式為utf-8
如下圖所示:
下載地址為: https://download.csdn.net/download/qq_37997682/11214644
如果覺得不錯,點個贊唄~