一、前言
有時我們需要在表格(QTableWidget)、樹狀欄(QTreeWidget)中直觀顯示任務進度或消耗百分比,達到報表顯示的形式,可通過重寫QLabel的方式實現。
1、進度條控制元件功能
1)可設定值動態變化
2)可設定警戒值
3)可設定正常顏色和報警顏色
4)可設定邊框漸變顏色
5)可設定變化時每次移動的步長
6)可設定錯誤時顯示錯誤描述
7)可設定顯示值保留小數的位數
8)可設定邊框圓角角度/背景進度圓角角度/頭部圓角角度
2、實現效果
二、實現過程
1、執行環境Qt5.5 VS2013
2、繼承QLabel重寫ProgressLabel控制元件


1 /***********************************************************************
2 作者:liangtianmanyue(QQ:1660941209) 2021-05-30
3 功能:進度控制元件
4 1、可設定值動態變化
5 2、可設定警戒值
6 3、可設定正常顏色和報警顏色
7 4、可設定邊框漸變顏色
8 5、可設定變化時每次移動的步長
9 6、可設定錯誤時顯示錯誤描述
10 6、可設定顯示值保留小數的位數
11 8、可設定邊框圓角角度/背景進度圓角角度/頭部圓角角度
12 ************************************************************************/
13
14 #ifndef PROGRESS_LABEL_H
15 #define PROGRESS_LABEL_H
16
17 #include <QLabel>
18 #include <QWidget>
19
20 #ifdef Plugin
21 #if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
22 #include <QtDesigner/QDesignerExportWidget>
23 #else
24 #include <QtUiPlugin/QDesignerExportWidget>
25 #endif
26
27 class QDESIGNER_WIDGET_EXPORT ProgressLabel : public QLabel
28 #else
29 class ProgressLabel : public QLabel
30 #endif
31 {
32 Q_OBJECT
33 Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
34 Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue)
35 Q_PROPERTY(double value READ getValue WRITE setValue)
36 Q_PROPERTY(double alarmValue READ getAlarmValue WRITE setAlarmValue)
37
38 Q_PROPERTY(double step READ getStep WRITE setStep)
39 Q_PROPERTY(int decimals READ getDecimals WRITE setDecimals)
40 Q_PROPERTY(int borderRadius READ getBorderRadius WRITE setBorderRadius)
41 Q_PROPERTY(int bgRadius READ getBgRadius WRITE setBgRadius)
42 Q_PROPERTY(int headRadius READ getHeadRadius WRITE setHeadRadius)
43
44 Q_PROPERTY(QColor borderColorStart READ getBorderColorStart WRITE setBorderColorStart)
45 Q_PROPERTY(QColor borderColorEnd READ getBorderColorEnd WRITE setBorderColorEnd)
46
47 Q_PROPERTY(QColor alarmColorStart READ getAlarmColorStart WRITE setAlarmColorStart)
48 Q_PROPERTY(QColor alarmColorEnd READ getAlarmColorEnd WRITE setAlarmColorEnd)
49
50 Q_PROPERTY(QColor normalColorStart READ getNormalColorStart WRITE setNormalColorStart)
51 Q_PROPERTY(QColor normalColorEnd READ getNormalColorEnd WRITE setNormalColorEnd)
52
53 public:
54 explicit ProgressLabel(QWidget *parent = 0);
55 ~ProgressLabel();
56
57 protected:
58 void paintEvent(QPaintEvent *);
59 void drawBg(QPainter *painter);
60
61 private slots:
62 void updateValue();
63
64 public:
65 double getMinValue() const;
66 double getMaxValue() const;
67 double getValue() const;
68 double getAlarmValue() const;
69
70 double getStep() const;
71 int getBorderRadius() const;
72 int getBgRadius() const;
73 int getHeadRadius() const;
74
75 QColor getBorderColorStart() const;
76 QColor getBorderColorEnd() const;
77
78 QColor getAlarmColorStart() const;
79 QColor getAlarmColorEnd() const;
80
81 QColor getNormalColorStart() const;
82 QColor getNormalColorEnd() const;
83
84 QSize sizeHint() const;
85 QSize minimumSizeHint() const;
86
87 public Q_SLOTS:
88 //設定範圍值
89 void setRange(double minValue, double maxValue);
90 void setRange(int minValue, int maxValue);
91
92 //設定最大最小值
93 void setMinValue(double minValue);
94 void setMaxValue(double maxValue);
95
96 //設定顯示值
97 void setValue(double value);
98 void setValue(int value);
99
100 //設定警戒值
101 void setAlarmValue(double alarmValue);
102 void setAlarmValue(int alarmValue);
103
104 //設定步長
105 void setStep(double step);
106 void setStep(int step);
107
108 //小數點位數
109 int getDecimals();
110 void setDecimals(int decimals);
111
112 //設定邊框圓角角度
113 void setBorderRadius(int borderRadius);
114 //設定背景圓角角度
115 void setBgRadius(int bgRadius);
116 //設定頭部圓角角度
117 void setHeadRadius(int headRadius);
118
119 //設定邊框漸變顏色
120 void setBorderColorStart(const QColor &borderColorStart);
121 void setBorderColorEnd(const QColor &borderColorEnd);
122
123 //設定報警時的漸變顏色
124 void setAlarmColorStart(const QColor &alarmColorStart);
125 void setAlarmColorEnd(const QColor &alarmColorEnd);
126
127 //設定電正常時的漸變顏色
128 void setNormalColorStart(const QColor &normalColorStart);
129 void setNormalColorEnd(const QColor &normalColorEnd);
130
131 //正常、異常顯示
132 void setNormalState();
133 void setErrorText(const QString &text);
134
135 Q_SIGNALS:
136 void valueChanged(double value);
137
138 private:
139 bool m_IsError; //是否出錯
140 QString m_ErrorText; //錯誤描述
141
142 double minValue; //最小值
143 double maxValue; //最大值
144 double value; //目標電量
145 double alarmValue; //電池電量警戒值
146 int decimals; //顯示小數點後位數
147 double step; //每次移動的步長
148 int borderRadius; //邊框圓角角度
149 int bgRadius; //背景進度圓角角度
150 int headRadius; //頭部圓角角度
151
152 QColor borderColorStart; //邊框漸變開始顏色
153 QColor borderColorEnd; //邊框漸變結束顏色
154
155 QColor alarmColorStart; //電池低電量時的漸變開始顏色
156 QColor alarmColorEnd; //電池低電量時的漸變結束顏色
157
158 QColor normalColorStart; //電池正常電量時的漸變開始顏色
159 QColor normalColorEnd; //電池正常電量時的漸變結束顏色
160
161 bool isForward; //是否往前移
162 double currentValue; //當前電量
163 QRectF batteryRect; //電池主體區域
164 QTimer *timer; //繪製定時器
165 };
166
167 #endif // PROGRESS_LABEL_H
ProgressLabel定義
3、重寫paintEvent事件,根據是否有出錯,繪製出錯資訊或值


1 void ProgressLabel::paintEvent(QPaintEvent *)
2 {
3 //繪製準備工作,啟用反鋸齒
4 QPainter painter(this);
5 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
6
7 //獲取邊框區域
8 QPointF topLeft(2, 2);
9 QPointF bottomRight(width() - 4, height() - 2);
10 batteryRect = QRectF(topLeft, bottomRight);
11 //繪製背景
12 drawBg(&painter);
13 }
14
15 void ProgressLabel::drawBg(QPainter *painter)
16 {
17 if(!m_IsError)
18 {
19 painter->save();
20 QLinearGradient batteryGradient(QPointF(0, 0), QPointF(0, height()));
21 if (currentValue >= alarmValue)
22 {
23 batteryGradient.setColorAt(0.0, alarmColorStart);
24 batteryGradient.setColorAt(1.0, alarmColorEnd);
25 }
26 else
27 {
28 batteryGradient.setColorAt(0.0, normalColorStart);
29 batteryGradient.setColorAt(1.0, normalColorEnd);
30 }
31
32 double min = qMin(width(), height());
33 int margin = min / 20;
34 double unit = (batteryRect.width() - (margin * 2)) / 100;
35 double width = currentValue * unit;
36 QPointF topLeft(batteryRect.topLeft().x() + margin, batteryRect.topLeft().y() + margin);
37 QPointF bottomRight(width + margin + 5, batteryRect.bottomRight().y() - margin);
38 QRectF rect(topLeft, bottomRight);
39
40 painter->setPen(Qt::NoPen);
41 painter->setBrush(batteryGradient);
42 painter->drawRoundedRect(rect, bgRadius, bgRadius);
43 painter->restore();
44 }
45
46 //寫進度
47 painter->save();
48 QPen pen(Qt::SolidLine);
49 pen.setWidth(1);
50 if(m_IsError)
51 pen.setColor(Qt::red);
52 else
53 pen.setColor(Qt::black);
54 painter->setPen(pen);
55 painter->setBrush(Qt::NoBrush);
56 if(m_IsError)
57 painter->drawText(batteryRect, Qt::AlignCenter, m_ErrorText);
58 else
59 painter->drawText(batteryRect, Qt::AlignCenter, QString("%1%").arg(currentValue, 0, 'f', decimals));
60 painter->restore();
61 }
控制元件繪製
4、重新整理值時採用定時器定時重新整理方式,達到動態效果


1 timer = new QTimer(this);
2 timer->setInterval(10);
3 connect(timer, SIGNAL(timeout()), this, SLOT(updateValue()));
建立定時器


1 void ProgressLabel::updateValue()
2 {
3 if (isForward)
4 {
5 currentValue -= step;
6
7 if (currentValue <= value)
8 {
9 timer->stop();
10 currentValue = value;//保持真實性
11 }
12 }
13 else
14 {
15 currentValue += step;
16
17 if (currentValue >= value)
18 {
19 timer->stop();
20 currentValue = value;//保持真實性
21 }
22 }
23
24 this->update();
25 }
按step值重新整理
5、外部設定值的時候,清除錯誤標誌,並啟動定時器


1 void ProgressLabel::setValue(double value)
2 {
3 m_IsError = false;
4 //值和當前值一致則無需處理
5 if (value == this->value)
6 return;
7
8 //值小於最小值則取最小值,大於最大值則取最大值
9 if (value < minValue)
10 value = minValue;
11 else if (value > maxValue)
12 value = maxValue;
13
14 if (value > currentValue)
15 isForward = false;
16 else if (value < currentValue)
17 isForward = true;
18 else
19 return;
20
21 this->value = value;
22 this->update();
23 emit valueChanged(value);
24 timer->start();
25 }
設定值