Qt編寫自定義控制元件21-圓弧儀表盤
一、前言
圓弧儀表盤在整個自定義控制元件大全中也稍微遇到了技術難點,比如背景透明,如果採用以前畫圓形畫扇形的方式繪製,肯定很難形成背景透明,需要用到切割,最後換了一種繪製方法,採用繪製圓弧的方式,即使用drawArc方法,這個方法有個注意點就是值要*16,我也一直沒有搞懂為什麼要*16,幫助文件也是這麼寫的,那就按照幫助文件來吧,具體也就沒有深究下去。
在用qpainter繪製準備工作中,如果先將繪製座標的中心點移動到區域的中心,painter。translate(width / 2, height / 2); 然後對座標系進行寬高風向的縮放200倍,painter。scale(side / 200。0, side / 200。0);這樣的方式繪製出來,只要指定了半徑或者字型指定了大小,以後都是會根據這個標準自動縮放的,這樣就做到了自適應任何大小字型自動變化,我也是突然之間發現的這個巧妙的用法。
二、實現的功能
* 1:可設定範圍值,支援負數值
* 2:可設定精確度,最大支援小數點後3位
* 3:可設定大刻度數量/小刻度數量
* 4:可設定開始旋轉角度/結束旋轉角度
* 5:可設定是否啟用動畫效果以及動畫效果每次移動的步長
* 6:可設定外圓背景/內圓背景/餅圓三種顏色/刻度尺顏色/文字顏色
* 7:自適應窗體拉伸,刻度尺和文字自動縮放
* 8:可自由拓展各種漸變色,各圓的半徑
* 9:指示器樣式可選擇 圓形指示器 指標指示器 圓角指標指示器 三角形指示器
三、效果圖
四、標頭檔案程式碼
#ifndef GAUGEARC_H
#define GAUGEARC_H
/**
* 圓弧儀表盤控制元件 作者:feiyangqingyun(QQ:517216493) 2016-12-16
* 1:可設定範圍值,支援負數值
* 2:可設定精確度,最大支援小數點後3位
* 3:可設定大刻度數量/小刻度數量
* 4:可設定開始旋轉角度/結束旋轉角度
* 5:可設定是否啟用動畫效果以及動畫效果每次移動的步長
* 6:可設定外圓背景/內圓背景/餅圓三種顏色/刻度尺顏色/文字顏色
* 7:自適應窗體拉伸,刻度尺和文字自動縮放
* 8:可自由拓展各種漸變色,各圓的半徑
* 9:指示器樣式可選擇 圓形指示器 指標指示器 圓角指標指示器 三角形指示器
*/
#include
#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include
#else
#include
#endif
class
QDESIGNER_WIDGET_EXPORT
GaugeArc
:
public
QWidget
#else
class
GaugeArc
:
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
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
(
QColor
arcColor
READ
getArcColor
WRITE
setArcColor
)
Q_PROPERTY
(
QColor
scaleColor
READ
getScaleColor
WRITE
setScaleColor
)
Q_PROPERTY
(
QColor
scaleNumColor
READ
getScaleNumColor
WRITE
setScaleNumColor
)
Q_PROPERTY
(
QColor
pointerColor
READ
getPointerColor
WRITE
setPointerColor
)
Q_PROPERTY
(
QColor
textColor
READ
getTextColor
WRITE
setTextColor
)
Q_PROPERTY
(
PointerStyle
pointerStyle
READ
getPointerStyle
WRITE
setPointerStyle
)
public
:
enum
PointerStyle
{
PointerStyle_Circle
=
0
,
//圓形指示器
PointerStyle_Indicator
=
1
,
//指標指示器
PointerStyle_IndicatorR
=
2
,
//圓角指標指示器
PointerStyle_Triangle
=
3
//三角形指示器
};
explicit
GaugeArc
(
QWidget
*
parent
=
0
);
~
GaugeArc
();
protected
:
void
paintEvent
(
QPaintEvent
*
);
void
drawArc
(
QPainter
*
painter
);
void
drawScale
(
QPainter
*
painter
);
void
drawScaleNum
(
QPainter
*
painter
);
void
drawPointerCircle
(
QPainter
*
painter
);
void
drawPointerIndicator
(
QPainter
*
painter
);
void
drawPointerIndicatorR
(
QPainter
*
painter
);
void
drawPointerTriangle
(
QPainter
*
painter
);
void
drawRoundCircle
(
QPainter
*
painter
);
void
drawCenterCircle
(
QPainter
*
painter
);
void
drawValue
(
QPainter
*
painter
);
private
slots
:
void
updateValue
();
private
:
double
minValue
;
//最小值
double
maxValue
;
//最大值
double
value
;
//目標值
int
precision
;
//精確度,小數點後幾位
int
scaleMajor
;
//大刻度數量
int
scaleMinor
;
//小刻度數量
int
startAngle
;
//開始旋轉角度
int
endAngle
;
//結束旋轉角度
bool
animation
;
//是否啟用動畫顯示
double
animationStep
;
//動畫顯示時步長
QColor
arcColor
;
//圓弧顏色
QColor
scaleColor
;
//刻度尺顏色
QColor
scaleNumColor
;
//刻度值顏色
QColor
pointerColor
;
//指標顏色
QColor
textColor
;
//文字顏色
PointerStyle
pointerStyle
;
//指標樣式
bool
reverse
;
//是否往回走
double
currentValue
;
//當前值
QTimer
*
timer
;
//定時器繪製動畫
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
;
QColor
getArcColor
()
const
;
QColor
getScaleColor
()
const
;
QColor
getScaleNumColor
()
const
;
QColor
getPointerColor
()
const
;
QColor
getTextColor
()
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
setScaleMajor
(
int
scaleMajor
);
//設定小刻度數量
void
setScaleMinor
(
int
scaleMinor
);
//設定開始旋轉角度
void
setStartAngle
(
int
startAngle
);
//設定結束旋轉角度
void
setEndAngle
(
int
endAngle
);
//設定是否啟用動畫顯示
void
setAnimation
(
bool
animation
);
//設定動畫顯示的步長
void
setAnimationStep
(
double
animationStep
);
//設定圓弧顏色
void
setArcColor
(
const
QColor
&
arcColor
);
//設定刻度尺顏色
void
setScaleColor
(
const
QColor
&
scaleColor
);
//設定刻度值顏色
void
setScaleNumColor
(
const
QColor
&
scaleNumColor
);
//設定指標顏色
void
setPointerColor
(
const
QColor
&
pointerColor
);
//設定文字顏色
void
setTextColor
(
const
QColor
&
textColor
);
//設定指標樣式
void
setPointerStyle
(
const
PointerStyle
&
pointerStyle
);
Q_SIGNALS
:
void
valueChanged
(
int
value
);
};
#endif
// GAUGEARC_H
五、核心程式碼
void
GaugeArc
::
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
);
//繪製圓弧
drawArc
(
&
painter
);
//繪製刻度線
drawScale
(
&
painter
);
//繪製刻度值
drawScaleNum
(
&
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
);
}
//繪製指標中心圓外邊框
drawRoundCircle
(
&
painter
);
//繪製指標中心圓
drawCenterCircle
(
&
painter
);
//繪製當前值
drawValue
(
&
painter
);
}
void
GaugeArc
::
drawArc
(
QPainter
*
painter
)
{
int
radius
=
98
;
painter
->
save
();
QPen
pen
;
pen
。
setColor
(
arcColor
);
pen
。
setWidthF
(
2
);
painter
->
setPen
(
pen
);
painter
->
setBrush
(
Qt
::
NoBrush
);
//計算總範圍角度,當前值範圍角度,剩餘值範圍角度
double
angleAll
=
360。0
-
startAngle
-
endAngle
;
double
angleCurrent
=
angleAll
*
((
currentValue
-
minValue
)
/
(
maxValue
-
minValue
));
double
angleOther
=
angleAll
-
angleCurrent
;
//繪製外邊框圓弧
QRectF
rect
=
QRectF
(
-
radius
,
-
radius
,
radius
*
2
,
radius
*
2
);
painter
->
drawArc
(
rect
,
(
270
-
startAngle
-
angleCurrent
)
*
16
,
angleCurrent
*
16
);
painter
->
drawArc
(
rect
,
(
270
-
startAngle
-
angleCurrent
-
angleOther
)
*
16
,
angleOther
*
16
);
//繪製裡邊框圓弧
radius
=
90
;
rect
=
QRectF
(
-
radius
,
-
radius
,
radius
*
2
,
radius
*
2
);
painter
->
drawArc
(
rect
,
(
270
-
startAngle
-
angleCurrent
)
*
16
,
angleCurrent
*
16
);
painter
->
drawArc
(
rect
,
(
270
-
startAngle
-
angleCurrent
-
angleOther
)
*
16
,
angleOther
*
16
);
painter
->
restore
();
}
void
GaugeArc
::
drawScale
(
QPainter
*
painter
)
{
int
radius
=
97
;
painter
->
save
();
painter
->
rotate
(
startAngle
);
int
steps
=
(
scaleMajor
*
scaleMinor
);
double
angleStep
=
(
360。0
-
startAngle
-
endAngle
)
/
steps
;
QPen
pen
;
pen
。
setColor
(
scaleColor
);
pen
。
setCapStyle
(
Qt
::
RoundCap
);
for
(
int
i
=
0
;
i
<=
steps
;
i
++
)
{
if
(
i
%
scaleMinor
==
0
)
{
pen
。
setWidthF
(
1。5
);
painter
->
setPen
(
pen
);
painter
->
drawLine
(
0
,
radius
-
12
,
0
,
radius
);
}
else
{
pen
。
setWidthF
(
1。0
);
painter
->
setPen
(
pen
);
painter
->
drawLine
(
0
,
radius
-
5
,
0
,
radius
);
}
painter
->
rotate
(
angleStep
);
}
painter
->
restore
();
}
void
GaugeArc
::
drawScaleNum
(
QPainter
*
painter
)
{
int
radius
=
75
;
painter
->
save
();
painter
->
setPen
(
scaleNumColor
);
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
;
QString
strValue
=
QString
(
“%1”
)。
arg
((
double
)
value
,
0
,
‘f’
,
precision
);
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
GaugeArc
::
drawPointerCircle
(
QPainter
*
painter
)
{
int
radius
=
8
;
int
offset
=
30
;
painter
->
save
();
painter
->
setPen
(
Qt
::
NoPen
);
painter
->
setBrush
(
pointerColor
);
painter
->
rotate
(
startAngle
);
double
degRotate
=
(
360。0
-
startAngle
-
endAngle
)
/
(
maxValue
-
minValue
)
*
(
currentValue
-
minValue
);
painter
->
rotate
(
degRotate
);
painter
->
drawEllipse
(
-
radius
,
radius
+
offset
,
radius
*
2
,
radius
*
2
);
painter
->
restore
();
}
void
GaugeArc
::
drawPointerIndicator
(
QPainter
*
painter
)
{
int
radius
=
75
;
painter
->
save
();
painter
->
setOpacity
(
0。8
);
painter
->
setPen
(
Qt
::
NoPen
);
painter
->
setBrush
(
pointerColor
);
QPolygon
pts
;
pts
。
setPoints
(
3
,
-
5
,
0
,
5
,
0
,
0
,
radius
);
painter
->
rotate
(
startAngle
);
double
degRotate
=
(
360。0
-
startAngle
-
endAngle
)
/
(
maxValue
-
minValue
)
*
(
currentValue
-
minValue
);
painter
->
rotate
(
degRotate
);
painter
->
drawConvexPolygon
(
pts
);
painter
->
restore
();
}
void
GaugeArc
::
drawPointerIndicatorR
(
QPainter
*
painter
)
{
int
radius
=
75
;
painter
->
save
();
QPen
pen
;
pen
。
setWidthF
(
1
);
pen
。
setColor
(
pointerColor
);
painter
->
setPen
(
pen
);
painter
->
setBrush
(
pointerColor
);
QPolygon
pts
;
pts
。
setPoints
(
3
,
-
5
,
0
,
5
,
0
,
0
,
radius
);
painter
->
rotate
(
startAngle
);
double
degRotate
=
(
360。0
-
startAngle
-
endAngle
)
/
(
maxValue
-
minValue
)
*
(
currentValue
-
minValue
);
painter
->
rotate
(
degRotate
);
painter
->
drawConvexPolygon
(
pts
);
//增加繪製圓角直線,與之前三角形重疊,形成圓角指標
pen
。
setCapStyle
(
Qt
::
RoundCap
);
pen
。
setWidthF
(
4
);
painter
->
setPen
(
pen
);
painter
->
drawLine
(
0
,
0
,
0
,
radius
);
painter
->
restore
();
}
void
GaugeArc
::
drawPointerTriangle
(
QPainter
*
painter
)
{
int
radius
=
10
;
int
offset
=
55
;
painter
->
save
();
painter
->
setPen
(
Qt
::
NoPen
);
painter
->
setBrush
(
pointerColor
);
QPolygon
pts
;
pts
。
setPoints
(
3
,
-
5
,
0
+
offset
,
5
,
0
+
offset
,
0
,
radius
+
offset
);
painter
->
rotate
(
startAngle
);
double
degRotate
=
(
360。0
-
startAngle
-
endAngle
)
/
(
maxValue
-
minValue
)
*
(
currentValue
-
minValue
);
painter
->
rotate
(
degRotate
);
painter
->
drawConvexPolygon
(
pts
);
painter
->
restore
();
}
void
GaugeArc
::
drawRoundCircle
(
QPainter
*
painter
)
{
int
radius
=
12
;
painter
->
save
();
painter
->
setOpacity
(
0。5
);
painter
->
setPen
(
Qt
::
NoPen
);
painter
->
setBrush
(
pointerColor
);
painter
->
drawEllipse
(
-
radius
,
-
radius
,
radius
*
2
,
radius
*
2
);
painter
->
restore
();
}
void
GaugeArc
::
drawCenterCircle
(
QPainter
*
painter
)
{
int
radius
=
8
;
painter
->
save
();
painter
->
setPen
(
Qt
::
NoPen
);
painter
->
setBrush
(
pointerColor
);
painter
->
drawEllipse
(
-
radius
,
-
radius
,
radius
*
2
,
radius
*
2
);
painter
->
restore
();
}
void
GaugeArc
::
drawValue
(
QPainter
*
painter
)
{
int
radius
=
100
;
painter
->
save
();
painter
->
setPen
(
textColor
);
QFont
font
;
font
。
setPixelSize
(
30
);
painter
->
setFont
(
font
);
QRectF
textRect
(
-
radius
,
radius
/
2
,
radius
*
2
,
radius
/
3
);
QString
strValue
=
QString
(
“%1”
)。
arg
((
double
)
currentValue
,
0
,
‘f’
,
precision
);
painter
->
drawText
(
textRect
,
Qt
::
AlignCenter
,
strValue
);
painter
->
restore
();
}
六、控制元件介紹
1。 超過146個精美控制元件,涵蓋了各種儀表盤、進度條、進度球、指南針、曲線圖、標尺、溫度計、導航條、導航欄,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/1tD9v1Y
PfE2fgYoK6lqUr1Q
提取碼:lyhk
- 自定義控制元件+屬性設計器欣賞:
https://
pan。baidu。com/s/1l6L3rK
SiLu_uYi7lnL3ibQ
提取碼:tmvl
- 下載連結中包含了各個版本的動態庫檔案,所有控制元件的標頭檔案,使用demo。
- 自定義控制元件外掛開放動態庫dll使用(永久免費),無任何後門和限制,請放心使用。
- 目前已提供26個版本的dll,其中包括了qt5。12。3 msvc2017 32+64 mingw 32+64 的。
- 不定期增加控制元件和完善控制元件,不定期更新SDK,歡迎各位提出建議,謝謝!
- widget版本(QQ:517216493)qml版本(QQ:373955953)三峰駝(QQ:278969898)。
- 濤哥的知乎專欄 Qt進階之路 Qt進階之路
- 歡迎關注微信公眾號【高效程式設計師】,C++/Python、學習方法、寫作技巧、熱門技術、職場發展等內容,乾貨多多,福利多多!