Qt绘制电池进度条(paintEvent)

目录

前言

一、效果图

二、主要代码和思路

       1.电池边框

       2.电池头

       3.电池电量

       4.绑定滑动条

       5.添加动画效果

源码地址


前言

        做了一个电池的进度条,分享一下,适合初学者,开发环境是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

  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
您可以通过继承 QProgressBar 类并重新实现绘制函数来自定义 Qt 进度条。 以下是一个示例代码: ```cpp #include <QtWidgets> class CustomProgressBar : public QProgressBar { public: explicit CustomProgressBar(QWidget* parent = nullptr) : QProgressBar(parent) { setMinimum(0); setMaximum(100); } protected: void paintEvent(QPaintEvent* event) override { QPainter painter(this); // 绘制背景 painter.fillRect(rect(), Qt::white); // 绘制进度条 int progressWidth = static_cast<int>(rect().width() * static_cast<double>(value()) / maximum()); QRect progressRect(rect().topLeft(), QSize(progressWidth, rect().height())); painter.fillRect(progressRect, Qt::blue); // 绘制文本 QString text = QString::number(value()) + "%"; painter.setPen(Qt::black); painter.drawText(rect(), Qt::AlignCenter, text); } }; int main(int argc, char** argv) { QApplication app(argc, argv); QMainWindow mainWindow; QWidget* centralWidget = new QWidget(&mainWindow); QVBoxLayout* layout = new QVBoxLayout(centralWidget); CustomProgressBar* progressBar = new CustomProgressBar(&mainWindow); progressBar->setValue(50); layout->addWidget(progressBar); mainWindow.setCentralWidget(centralWidget); mainWindow.show(); return app.exec(); } ``` 在此示例中,我们创建了一个名为 `CustomProgressBar` 的自定义进度条类。我们重新实现了 `paintEvent` 函数来绘制自己的进度条样式。在这个示例中,我们使用白色作为背景,蓝色作为进度条的颜色,并在进度条上方绘制了当前的进度文本。 您可以根据自己的需求修改绘制函数以实现您想要的效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Q泥T挖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值