一、前言
有時我們需要在表格(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 mainRect; //主體區域 164 QTimer *timer; //繪製定時器 165 }; 166 167 #endif // PROGRESS_LABEL_H
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 mainRect = 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 = (mainRect.width() - (margin * 2)) / 100; 35 double width = currentValue * unit; 36 QPointF topLeft(mainRect.topLeft().x() + margin, mainRect.topLeft().y() + margin); 37 QPointF bottomRight(width + margin + 5, mainRect.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(mainRect, Qt::AlignCenter, m_ErrorText); 58 else 59 painter->drawText(mainRect, 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 }
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 }