通过重载paintEvent方法,实现电池外观绘制,其中的动画效果通过定义QPropertyAnimation变量实现,动画效果也可以尝试定时器实现,电池的大小根据窗口大小动态调整,支持电池颜色、动画时长等自定义,电池颜色是通过阶梯变化;具体实现如下,仁者见仁,智者见智,欢迎各位同仁不吝赐教。
头文件
#ifndef QBATTERY_H
#define QBATTERY_H
#include
#include
/**
* 电池电量控件 作者:xujidong
* 2022-9-5s
* 1. 可以设置电池电池尺寸,并且电池尺寸可以跟随控件大小比例切换
* 2. 可以设置电池电量,电池电量以动画的形式变化。
* 3. 可以设置电量变化动画时间。
* 2. 可设置电池电量警戒值。
* 3. 可设置电池电量正常颜色和报警颜色。
* 4. 可设置边框颜色。
* 问题:
* 1. 当直接调用设置电量属性接口,不能实现动画效果
* 2. 还没有显示充电状态
*/
class QBattery : public QWidget
{
Q_OBJECT
Q_PROPERTY(double minValue READ minValue WRITE setMinValue)
Q_PROPERTY(double maxValue READ maxValue WRITE setMaxValue)
Q_PROPERTY(double value READ value WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(double warningValue READ warningValue WRITE setWarningValue)
Q_PROPERTY(QColor warningColorStart READ warningColorStart WRITE setWarningColorStart)
Q_PROPERTY(QColor warningColorEnd READ warningColorEnd WRITE setWarningColorEnd)
Q_PROPERTY(QColor normalColorStart READ normalColorStart WRITE setNormalColorStart)
Q_PROPERTY(QColor normalColorEnd READ normalColorEnd WRITE setNormalColorEnd)
Q_PROPERTY(int animatonMsecs READ animationMsecs WRITE setAnimationMsecs);
// Q_PROPERTY(double step READ getStep WRITE setStep)
// Q_PROPERTY(int borderWidth READ getBorderWidth WRITE setBorderWidth)
// 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 borderColor READ borderColor WRITE setBorderColor)
// Q_PROPERTY(QColor borderColorEnd READ getBorderColorEnd WRITE setBorderColorEnd)
public:
explicit QBattery(QWidget *parent = 0);
~QBattery();
protected:
void paintEvent(QPaintEvent *);
// void drawBorder(QPainter *painter);
// void drawBg(QPainter *painter);
// void drawHead(QPainter *painter);
//private slots:
// void updateValue();
private:
QPropertyAnimation* barreryValueAnimation;
double mMinValue = 0; //电池电量最小值
double mMaxValue = 100; //电池电量最大值
double mWarningValue; //电池电量警戒值
int mBorderWidth = 0; //边框粗细
int mBorderRadius; //边框圆角角度
// int bgRadius; //背景进度圆角角度
// int headRadius; //头部圆角角度
int mBatteryWidth = 0; //电池宽度
int mBatteryHeight = 0; //电池高度
int mBatteryHeadWidth = 0; //电池柱头宽度
int mBatteryHeadHeight = 0; //电池柱头宽度
int mElectricBorder; //电量填充边界
int mAnimationMsecs; //电池电量动画运行时间 单位毫秒
QColor mBorderColor; //边框渐变颜色
QColor mWarningColorStart; //电池低电量时的渐变开始颜色
QColor mWarningColorEnd; //电池低电量时的渐变结束颜色
QColor mNormalColorStart; //电池正常电量时的渐变开始颜色
QColor mNormalColorEnd; //电池正常电量时的渐变结束颜色
double mCurrentValue; //当前电量
// QRectF batteryRect; //电池主体区域
// QTimer *timer; //绘制定时器
void setValue(const double); //设置电池电量
public:
double minValue() const;
void setMinValue(double minValue);
double maxValue() const;
void setMaxValue(double maxValue);
double value() const;
double warningValue() const;
// double getStep() const;
// int getBorderWidth() const;
// int getBorderRadius() const;
// int getBgRadius() const;
// int getHeadRadius() const;
QColor borderColor() const;
void setBorderColor(const QColor &borderColor);//设置边框颜色
// QColor getBorderColorEnd() const;
//设置电池电量报警时的渐变颜色
QColor warningColorStart() const;
void setWarningColorStart(const QColor &warningColorStart);
QColor warningColorEnd() const;
void setWarningColorEnd(const QColor &warningColorEnd);
QColor normalColorStart() const;
void setNormalColorStart(const QColor &normalColorStart);
QColor normalColorEnd() const;
void setNormalColorEnd(const QColor &normalColorEnd);
int animationMsecs() const;
void setAnimationMsecs(const int animationMsecs);
// QSize sizeHint() const;
// QSize minimumSizeHint() const;
public Q_SLOTS:
// //设置范围值
// void setRange(double minValue, double maxValue);
// void setRange(int minValue, int maxValue);
// //设置电池电量值
void setElecValue(int value);
void setElecValue(double value);
//设置电池电量警戒值
void setWarningValue(double);
void setWarningValue(int warningValue);
// //设置步长
// void setStep(double step);
// void setStep(int step);
// //设置边框粗细
// void setBorderWidth(int borderWidth);
// //设置边框圆角角度
// void setBorderRadius(int borderRadius);
// //设置背景圆角角度
// void setBgRadius(int bgRadius);
// //设置头部圆角角度
// void setHeadRadius(int headRadius);
// void setBorderColorEnd(const QColor &borderColorEnd);
Q_SIGNALS:
void valueChanged(double value);
};
#endif // QBATTERY_H
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
源文件
#include "qbattery.h"
#include
#include
#include
QBattery::QBattery(QWidget *parent)
{
mBorderColor = QColor(100, 100, 100);
mNormalColorStart = QColor(50, 205, 51); //电池正常电量时的渐变开始颜色
mNormalColorEnd = QColor(60, 179, 133); //电池正常电量时的渐变结束颜色
mWarningColorStart = QColor(250, 118, 113);
mWarningColorEnd = QColor(204, 38, 38);
mBorderRadius = 1;
mBorderWidth = 2;
mBatteryHeadWidth = 6;
mBatteryHeadHeight = 20;
mBatteryWidth = 80;
mBatteryHeight = 40;
mElectricBorder = 2;
mWarningValue = 20.0;
mCurrentValue = 60.0;
mAnimationMsecs = 500; //动画运行时间,单位微妙
barreryValueAnimation = new QPropertyAnimation(this,"value");
}
QBattery::~QBattery()
{
delete barreryValueAnimation;
}
void QBattery::paintEvent(QPaintEvent *paintEvent)
{
Q_UNUSED(paintEvent)
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing); //设置抗锯齿
int batteryWidth = mBatteryWidth + mBatteryHeadWidth + 3*mBorderWidth; //计算电池总体的长和宽
int batteryHeight = mBatteryHeight +2*mBorderWidth;
float ratioX = (float)width()/batteryWidth; //计算电池与实际窗口的长宽比
float ratioY = (float)height()/batteryHeight;
int windowWidth;
int windowHeight;
//根据窗口缩放,计算实际缩放后的窗口大小
if(ratioX > ratioY){
windowWidth = batteryWidth*ratioY;
windowHeight = height();
}else{
windowWidth = width();
windowHeight = batteryHeight*ratioX;
}
//计算窗口缩放后的电池的长宽等数据
float ratio = qMin(ratioX,ratioY);
int ratioWidth = mBatteryWidth*ratio;
int ratioHeight = mBatteryHeight*ratio;
int ratioBorderWidth = mBorderWidth*ratio;
int ratioBatteryHeadWidth = mBatteryHeadWidth*ratio;
int ratioBatteruHeadHeight = mBatteryHeadHeight*ratio;
int ratioElectricBorder = mElectricBorder*ratio;
painter.setViewport(0,0,windowWidth,windowHeight); //设置视图窗口
painter.setWindow(-windowWidth/2,-windowHeight/2,windowWidth,windowHeight);//设置窗口坐标原点为视口区域
//的中心,只有视图坐标尺寸和窗口坐标尺寸比例相同时,才不会导致图形拉伸变形
//绘制电池轮廓
QPen pen;
pen.setWidth(ratioBorderWidth);
pen.setColor(mBorderColor);
painter.setPen(pen);
painter.drawRect(-ratioWidth/2,-ratioHeight/2,ratioWidth,ratioHeight);
//绘制电池正极
QBrush brush;
brush.setColor(mBorderColor);
brush.setStyle(Qt::SolidPattern); //画刷填充样式
painter.setBrush(brush);
painter.drawRect(ratioWidth/2,-ratioBatteruHeadHeight/2,ratioBatteryHeadWidth,ratioBatteruHeadHeight);
//填充电池颜色
painter.setPen(Qt::NoPen);
QLinearGradient linearGradient(-ratioWidth/2+ratioElectricBorder,-ratioHeight/2+ratioElectricBorder,
-ratioWidth/2+ratioElectricBorder,
-ratioHeight/2+ratioElectricBorder+ratioHeight-2*ratioElectricBorder);
// brush.setStyle(Qt::CrossPattern); //画刷填充样式
if(mCurrentValue > mWarningValue){
linearGradient.setColorAt(0,mNormalColorStart);
linearGradient.setColorAt(1,mNormalColorEnd);
brush.setStyle(Qt::LinearGradientPattern);
painter.setBrush(linearGradient);
painter.drawRect(-ratioWidth/2+ratioElectricBorder,-ratioHeight/2+ratioElectricBorder,
mCurrentValue/100*(ratioWidth-2*ratioElectricBorder),ratioHeight-2*ratioElectricBorder);
}else{
linearGradient.setColorAt(0,mWarningColorStart);
linearGradient.setColorAt(1,mWarningColorEnd);
painter.setBrush(linearGradient);
painter.drawRect(-ratioWidth/2+ratioElectricBorder,-ratioHeight/2+ratioElectricBorder,
mCurrentValue/100*(ratioWidth-2*ratioElectricBorder),ratioHeight-2*ratioElectricBorder);
}
//绘制电池电量文字
QFont font = this->font();
qDebug()<<"font.pixelSize = "<<font.pixelSize();
font.setPixelSize(10*ratio);
this->setFont(font);
QFontMetrics textSize = QWidget::fontMetrics();
qDebug()<<"textSize.height() = "<<textSize.height()<<"textSize.maxWidth()"<<textSize.maxWidth();
QString powStr=QString::asprintf("%.2f%%",mCurrentValue);
QRect textRect=textSize.tightBoundingRect(powStr);//得到字符串的rect
pen.setColor("black"); //划线颜色
painter.setPen(pen);
painter.drawText(0-textRect.width()/2,textRect.height()/2,powStr);
}
double QBattery::value() const
{
return mCurrentValue;
}
void QBattery::setValue(const double value)
{
mCurrentValue = value;
this->repaint();
}
double QBattery::minValue() const
{
return mMinValue;
}
void QBattery::setMinValue(double minValue)
{
mMinValue = minValue;
}
double QBattery::maxValue() const
{
return mMaxValue;
}
void QBattery::setMaxValue(double maxValue)
{
mMaxValue = maxValue;
}
void QBattery::setElecValue(int value)
{
barreryValueAnimation->setDuration(mAnimationMsecs);
barreryValueAnimation->setStartValue(mCurrentValue);
barreryValueAnimation->setEndValue((double)value);
barreryValueAnimation->start();
}
void QBattery::setElecValue(double value)
{
barreryValueAnimation->setDuration(mAnimationMsecs);
barreryValueAnimation->setStartValue(mCurrentValue);
barreryValueAnimation->setEndValue(value);
barreryValueAnimation->start();
}
double QBattery::warningValue() const
{
return mWarningValue;
}
void QBattery::setWarningValue(double warningValue)
{
mWarningValue = warningValue;
this->repaint();
}
void QBattery::setWarningValue(int warningValue)
{
mWarningValue = (double)warningValue;
this->repaint();
}
QColor QBattery::borderColor() const
{
return mBorderColor;
}
void QBattery::setBorderColor(const QColor &borderColor)
{
mBorderColor = borderColor;
this->repaint();
}
QColor QBattery::warningColorStart() const
{
return mWarningColorStart;
}
void QBattery::setWarningColorStart(const QColor &warningColorStart)
{
mWarningColorStart = warningColorStart;
this->repaint();
}
QColor QBattery::warningColorEnd() const
{
return mWarningColorEnd;
}
void QBattery::setWarningColorEnd(const QColor &warningColorEnd)
{
mWarningColorEnd = warningColorEnd;
this->repaint();
}
QColor QBattery::normalColorStart() const
{
return mNormalColorStart;
}
void QBattery::setNormalColorStart(const QColor &normalColorStart)
{
mNormalColorStart = normalColorStart;
this->repaint();
}
QColor QBattery::normalColorEnd() const
{
return mNormalColorEnd;
}
void QBattery::setNormalColorEnd(const QColor &normalColorEnd)
{
mNormalColorEnd = normalColorEnd;
this->repaint();
}
int QBattery::animationMsecs() const
{
return mAnimationMsecs;
}
void QBattery::setAnimationMsecs(const int animationMsecs)
{
mAnimationMsecs = animationMsecs;
this->repaint();
}
#endif