有时我们需要在表格(QTableWidget)、树状栏(QTreeWidget)中直观显示任务进度或消耗百分比,达到报表显示的形式,可通过重写QLabel的方式实现。
1、进度条控件功能
1)可设置值动态变化
2)可设置警戒值
3)可设置正常颜色和报警颜色
4)可设置边框渐变颜色
5)可设置变化时每次移动的步长
6)可设置错误时显示错误描述
7)可设置显示值保留小数的位数
8)可设置边框圆角角度/背景进度圆角角度/头部圆角角度
2、实现效果
1、运行环境Qt5.5 VS2013
2、继承QLabel重写ProgressLabel控件
/*********************************************************************** 作者:liangtianmanyue(QQ:1660941209) 2021-05-30 功能:进度控件 1、可设置值动态变化 2、可设置警戒值 3、可设置正常颜色和报警颜色 4、可设置边框渐变颜色 5、可设置变化时每次移动的步长 6、可设置错误时显示错误描述 7、可设置显示值保留小数的位数 8、可设置边框圆角角度/背景进度圆角角度/头部圆角角度 ************************************************************************/ #ifndef PROGRESS_LABEL_H #define PROGRESS_LABEL_H #include#include #ifdef Plugin #if (QT_VERSION #else #include #endif class QDESIGNER_WIDGET_EXPORT ProgressLabel : public QLabel #else class ProgressLabel : public QLabel #endif { Q_OBJECT 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(double alarmValue READ getAlarmValue WRITE setAlarmValue) Q_PROPERTY(double step READ getStep WRITE setStep) Q_PROPERTY(int decimals READ getDecimals WRITE setDecimals) Q_PROPERTY(int borderRadius READ getBorderRadius WRITE setBorderRadius) Q_PROPERTY(int bgRadius READ getBgRadius WRITE setBgRadius) Q_PROPERTY(int headRadius READ getHeadRadius WRITE setHeadRadius) Q_PROPERTY(QColor borderColorStart READ getBorderColorStart WRITE setBorderColorStart) Q_PROPERTY(QColor borderColorEnd READ getBorderColorEnd WRITE setBorderColorEnd) Q_PROPERTY(QColor alarmColorStart READ getAlarmColorStart WRITE setAlarmColorStart) Q_PROPERTY(QColor alarmColorEnd READ getAlarmColorEnd WRITE setAlarmColorEnd) Q_PROPERTY(QColor normalColorStart READ getNormalColorStart WRITE setNormalColorStart) Q_PROPERTY(QColor normalColorEnd READ getNormalColorEnd WRITE setNormalColorEnd) public: explicit ProgressLabel(QWidget *parent = 0); ~ProgressLabel(); protected: void paintEvent(QPaintEvent *); void drawBg(QPainter *painter); private slots: void updateValue(); public: double getMinValue() const; double getMaxValue() const; double getValue() const; double getAlarmValue() const; double getStep() const; int getBorderRadius() const; int getBgRadius() const; int getHeadRadius() const; QColor getBorderColorStart() const; QColor getBorderColorEnd() const; QColor getAlarmColorStart() const; QColor getAlarmColorEnd() const; QColor getNormalColorStart() const; QColor getNormalColorEnd() 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 setAlarmValue(double alarmValue); void setAlarmValue(int alarmValue); //设置步长 void setStep(double step); void setStep(int step); //小数点位数 int getDecimals(); void setDecimals(int decimals); //设置边框圆角角度 void setBorderRadius(int borderRadius); //设置背景圆角角度 void setBgRadius(int bgRadius); //设置头部圆角角度 void setHeadRadius(int headRadius); //设置边框渐变颜色 void setBorderColorStart(const QColor &borderColorStart); void setBorderColorEnd(const QColor &borderColorEnd); //设置报警时的渐变颜色 void setAlarmColorStart(const QColor &alarmColorStart); void setAlarmColorEnd(const QColor &alarmColorEnd); //设置正常时的渐变颜色 void setNormalColorStart(const QColor &normalColorStart); void setNormalColorEnd(const QColor &normalColorEnd); //正常、异常显示 void setNormalState(); void setErrorText(const QString &text); Q_SIGNALS: void valueChanged(double value); private: bool m_IsError; //是否出错 QString m_ErrorText; //错误描述 double minValue; //最小值 double maxValue; //最大值 double value; //目标电量 double alarmValue; //警戒值 int decimals; //显示小数点后位数 double step; //每次移动的步长 int borderRadius; //边框圆角角度 int bgRadius; //背景进度圆角角度 int headRadius; //头部圆角角度 QColor borderColorStart; //边框渐变开始颜色 QColor borderColorEnd; //边框渐变结束颜色 QColor alarmColorStart; //超警戒值时的渐变开始颜色 QColor alarmColorEnd; //超警戒值时的渐变结束颜色 QColor normalColorStart; //正常时的渐变开始颜色 QColor normalColorEnd; //正常时的渐变结束颜色 bool isForward; //是否往前移 double currentValue; //当前值 QRectF mainRect; //主体区域 QTimer *timer; //绘制定时器 }; #endif // PROGRESS_LABEL_H
3、重写paintEvent事件,根据是否有出错,绘制出错信息或值
void ProgressLabel::paintEvent(QPaintEvent *) { //绘制准备工作,启用反锯齿 QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //获取边框区域 QPointF topLeft(2, 2); QPointF bottomRight(width() - 4, height() - 2); mainRect = QRectF(topLeft, bottomRight); //绘制背景 drawBg(&painter); } void ProgressLabel::drawBg(QPainter *painter) { if(!m_IsError) { painter->save(); QLinearGradient gradient(QPointF(0, 0), QPointF(0, height())); if (currentValue >= alarmValue) { gradient.setColorAt(0.0, alarmColorStart); gradient.setColorAt(1.0, alarmColorEnd); } else { gradient.setColorAt(0.0, normalColorStart); gradient.setColorAt(1.0, normalColorEnd); } double min = qMin(width(), height()); int margin = min / 20; double unit = (mainRect.width() - (margin * 2)) / 100; double width = currentValue * unit; QPointF topLeft(mainRect.topLeft().x() + margin, mainRect.topLeft().y() + margin); QPointF bottomRight(width + margin + , mainRect.bottomRight().y() - margin); QRectF rect(topLeft, bottomRight); painter->setPen(Qt::NoPen); painter->setBrush(gradient); painter->drawRoundedRect(rect, bgRadius, bgRadius); painter->restore(); } //写进度 painter->save(); QPen pen(Qt::SolidLine); pen.setWidth(1); if(m_IsError) pen.setColor(Qt::red); else pen.setColor(Qt::black); painter->setPen(pen); painter->setBrush(Qt::NoBrush); if(m_IsError) painter->drawText(mainRect, Qt::AlignCenter, m_ErrorText); else painter->drawText(mainRect, Qt::AlignCenter, QString("%1%").arg(currentValue, 0, 'f', decimals)); painter->restore(); }
4、刷新值时采用定时器定时刷新方式,达到动态效果
创建定时器
timer = new QTimer(this); timer->setInterval(10); connect(timer, SIGNAL(timeout()), this, SLOT(updateValue()));
按step值刷新
void ProgressLabel::updateValue() { if (isForward) { currentValue -= step; if (currentValue <= value) { timer->stop(); currentValue = value;//保持真实性 } } else { currentValue += step; if (currentValue >= value) { timer->stop(); currentValue = value;//保持真实性 } } this->update(); }
5、外部设置值的时候,清除错误标志,并启动定时器
void ProgressLabel::setValue(double value) { m_IsError = false; //值和当前值一致则无需处理 if (value == this->value) return; //值小于最小值则取最小值,大于最大值则取最大值 if (valuemaxValue) value = maxValue; if (value > currentValue) isForward = false; else if (value value = value; this->update(); emit valueChanged(value); timer->start(); }