您當前的位置:首頁 > 體育

Qt編寫自定義控制元件21-圓弧儀表盤

作者:由 劉典武 發表于 體育時間:2019-06-04

一、前言

圓弧儀表盤在整個自定義控制元件大全中也稍微遇到了技術難點,比如背景透明,如果採用以前畫圓形畫扇形的方式繪製,肯定很難形成背景透明,需要用到切割,最後換了一種繪製方法,採用繪製圓弧的方式,即使用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:指示器樣式可選擇 圓形指示器 指標指示器 圓角指標指示器 三角形指示器

三、效果圖

Qt編寫自定義控制元件21-圓弧儀表盤

四、標頭檔案程式碼

#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、學習方法、寫作技巧、熱門技術、職場發展等內容,乾貨多多,福利多多!