目录
前言
做了一个电池的进度条,分享一下,适合初学者,开发环境是Qt5.14.2+MSVC2017。写的比较啰嗦,想看源码的可以直接滑到最后有源码链接。
一、效果图
老规矩,先上图。
二、主要代码和思路
其实就是在paintEvent事件里用绘画工具把一个电池的图形画出来,可以把这个图形拆分一下,分成三部分:电池头、电池边框和电池电量。
1.电池边框
把电池头和电池边框的比例可以计算一下,我这里是把控件总宽度分成20份,让电池头占一份,其余的都是电池边框(如果你想做纵向的电池就用高度计算)。
void MyBattery::drawBetteryBorder(QPainter *painter)
{
double headLength = width() / 20; // 电池头的长度
double borderLength = width() - headLength; // 电池框的长度
// 绘制电池框
int borderWidth = 5; // 电池框的边框宽度
int borderRadius = 6; // 电池框的圆角弧度
QPointF topLeft(borderWidth, borderWidth);
QPointF bottomRight(borderLength, height() - borderWidth);
m_batteryRect = QRectF(topLeft, bottomRight);
painter->setPen(QPen(QColor(255, 255, 255), borderWidth));
painter->setBrush(Qt::NoBrush);
painter->drawRoundedRect(m_batteryRect, borderRadius, borderRadius);
}
运行效果如下:
2.电池头
画完电池框继续画电池头,先计算一下电池头的位置,我这里是把电池头放到了右边,所以水平方向就是从m_batteryRect.topRight().x()开始一直到整个控件的最右边,也就是width()的位置,然后电池头的高度我设置的是电池框高度的三分之一,所以垂直方向就是从height() / 3开始到height() - height() / 3的位置结束。
void MyBattery::drawBetteryHead(QPainter *painter)
{
QPointF headRectTopLeft(m_batteryRect.topRight().x(), height() / 3);
QPointF headRectBottomRight(width(), height() - height() / 3);
QRectF headRect(headRectTopLeft, headRectBottomRight);
int headRadius = 3; // 电池头部圆角弧度
painter->setPen(Qt::NoPen);
painter->setBrush(QColor(255,255,255));
painter->drawRoundedRect(headRect, headRadius, headRadius);
}
看一下运行效果:
3.电池电量
电池的电量显示在电池边框里面,所以需要先计算出电池边框内部的区域,然后把这一部分区域平分成100份,根据当前的电量来计算电量要显示多大的区域,根绝电量的不同还增加了警告色和正常色的区别,我设置的是电量20及以下为警告色(颜色可以根据自己的喜好更改)。
void MyBattery::drawBetteryLevel(QPainter *painter)
{
int currentValue = 20; // 当前电量值
int borderWidth = 5; // 电池框的边框宽度
int levelRadius = 5; // 电量圆角弧度
double unit = (m_batteryRect.width() - (borderWidth * 2)) / 100;
double width = currentValue * unit;
QPointF topLeft(m_batteryRect.topLeft().x() + borderWidth, m_batteryRect.topLeft().y() + borderWidth);
QPointF bottomRight(width + borderWidth + borderWidth, m_batteryRect.bottomRight().y() - borderWidth);
QRectF levelRect(topLeft, bottomRight);
QLinearGradient batteryGradient(levelRect.topLeft(), levelRect.bottomLeft());
if (currentValue <= 30) {
batteryGradient.setColorAt(0.0, QColor(250, 128, 114));
batteryGradient.setColorAt(1.0, QColor(205, 92, 92));
} else {
batteryGradient.setColorAt(0.0, QColor(50, 205, 50));
batteryGradient.setColorAt(1.0, QColor(60, 179, 113));
}
painter->setPen(Qt::NoPen);
painter->setBrush(batteryGradient);
painter->drawRoundedRect(levelRect, levelRadius, levelRadius);
}
正常色电量的运行效果:
警告色电量的运行效果:
4.绑定滑动条
电池的值由外部传递过来,这里我用一个滑动条进行绑定,绑定之前需要先写一个槽函数来处理一下滑动条的信号。
void MyBattery::slotUpdateLevel(int value)
{
// 值和当前值一致则无需处理
if (value == m_curValue) {
return;
}
// 值不在0-100的重置一下value的值
if(value < 0)
{
value = 0;
}
if(value > 100)
{
value = 100;
}
m_curValue = value;
update();
}
写完槽函数之后就可以把信号槽绑定上了。
connect(ui->horizontalSlider, &QSlider::valueChanged, ui->widget_battery, &MyBattery::slotUpdateLevel);
然后就可以用滑动条来控制电池的电量了。
5.添加动画效果
电池的值变化起来有点直白,这里用定时器给电池电量的变化加个动画的效果。思路就是不立刻将当前电量调整为目标电量,而是一点一点长上去,呈现动画的效果,创建一个定时器,设置每0.01秒涨0.5的电量。
// 计算电量是增加还是减少
if (value > m_curValue)
{
m_isValueAdd = true;
}
else if(value < m_curValue)
{
m_isValueAdd = false;
}
m_tarValue = value;
if(m_valueChangeTimer->isActive())
{
m_valueChangeTimer->stop();
}
m_valueChangeTimer->start();
void MyBattery::slotTimerOut()
{
double step = 0.5; // 每次变化的值
if (m_isValueAdd)
{
m_curValue += step;
if (m_curValue >= m_tarValue)
{
m_curValue = m_tarValue;
m_valueChangeTimer->stop();
}
}
else
{
m_curValue -= step;
if (m_curValue <= m_tarValue)
{
m_curValue = m_tarValue;
m_valueChangeTimer->stop();
}
}
update();
}
这里不会做动图,就没有放效果图。
源码地址
源码地址:https://download.csdn.net/download/qq_36129488/89011313