Qt中自定义 QmyBattery 电池组件开发

在 Qt 开发中,自定义 Widget 是实现个性化 UI 组件的核心方式,本文以QmyBattery电池组件为例,详细讲解如何基于QWidget子类化实现具备电量显示、警告阈值、样式自定义的电池控件,涵盖核心绘制逻辑、属性封装、尺寸适配等关键知识点。

一、组件设计思路

QmyBattery组件需实现以下核心功能:

  1. 可视化展示电池外形(主体 + 正极);
  2. 按百分比显示电量填充效果,支持正常 / 警告颜色切换;
  3. 封装电量、警告阈值等属性,支持外部设置 / 获取;
  4. 自适应控件尺寸,保持电池外观比例协调;
  5. 发射电量变化信号,支持与其他组件联动。

二、核心代码实现

1. 头文件(QmyBattery.h)

cpp 复制代码
#ifndef QMYBATTERY_H
#define QMYBATTERY_H

#include <QWidget>
#include <QPainter>
#include <QFontMetrics>

class QmyBattery : public QWidget
{
    Q_OBJECT
    // 注册属性
    Q_PROPERTY(int powerLevel READ powerLevel WRITE setPowerLevel NOTIFY powerLevelChanged)
    Q_PROPERTY(int warnLevel READ warnLevel WRITE setWarnLevel)
    Q_PROPERTY(QColor colorBorder READ colorBorder WRITE setColorBorder)
    Q_PROPERTY(QColor colorPower READ colorPower WRITE setColorPower)
    Q_PROPERTY(QColor colorWarning READ colorWarning WRITE setColorWarning)
    Q_PROPERTY(QColor colorBack READ colorBack WRITE setColorBack)

public:
    explicit QmyBattery(QWidget *parent = nullptr);

    // 属性获取接口:
    int powerLevel();        // 获取当前电量
    int warnLevel();         // 获取警告阈值
    QColor colorBorder();    // 获取边框颜色
    QColor colorPower();     // 获取正常电量颜色
    QColor colorWarning();   // 获取警告颜色
    QColor colorBack();      // 获取背景颜色

    // 属性设置接口:
    void setPowerLevel(int pow);    // 设置电量(触发重绘+信号)
    void setWarnLevel(int warn);    // 设置警告阈值(触发重绘)
    void setColorBorder(QColor color); // 修正拼写
    void setColorPower(QColor color);
    void setColorWarning(QColor color);
    void setColorBack(QColor color);

    // 重写尺寸提示,适配电池比例
    QSize sizeHint()const override;

signals:
    void powerLevelChanged(int pow); // 电量变化信号

protected:
    // 重写绘制事件,实现电池可视化
    void paintEvent(QPaintEvent *event) override;

private:
    // 成员变量:
    int mPowerLevel = 60;    // 默认电量60%
    int mWarnLevel = 20;     // 默认警告阈值20%
    QColor mColorBorder = Qt::black;   // 边框颜色
    QColor mColorPower = Qt::green;    // 正常电量颜色
    QColor mColorWarning = Qt::red;    // 警告颜色
    QColor mColorBack = Qt::white;     // 背景颜色
};

#endif // QMYBATTERY_H

2. 源文件(QmyBattery.cpp)

cpp 复制代码
#include "QmyBattery.h"

QmyBattery::QmyBattery(QWidget *parent) : QWidget(parent)
{
    // 初始化无额外逻辑,属性使用默认值
}

// ========== 属性获取接口 ==========
int QmyBattery::powerLevel()
{
    return mPowerLevel;
}

int QmyBattery::warnLevel()
{
    return mWarnLevel;
}


QColor QmyBattery::colorBorder()
{
    return mColorBorder;
}

QColor QmyBattery::colorPower()
{
    return mColorPower;
}

QColor QmyBattery::colorWarning()
{
    return mColorWarning;
}

QColor QmyBattery::colorBack()
{
    return mColorBack;
}

// ========== 属性设置接口 ==========
void QmyBattery::setPowerLevel(int pow)
{
    // 限制电量范围0-100,避免绘制异常
    mPowerLevel = qBound(0, pow, 100);
    emit powerLevelChanged(mPowerLevel); // 发射电量变化信号
    repaint(); // 触发重绘,更新显示
}

void QmyBattery::setWarnLevel(int warn)
{
    mWarnLevel = qBound(0, warn, 100); // 限制阈值范围0-100
    repaint();
}


void QmyBattery::setColorBorder(QColor color)
{
    mColorBorder = color;
    repaint();
}

void QmyBattery::setColorPower(QColor color)
{
    mColorPower = color;
    repaint();
}

void QmyBattery::setColorWarning(QColor color)
{
    mColorWarning = color;
    repaint();
}

void QmyBattery::setColorBack(QColor color)
{
    mColorBack = color;
    repaint();
}

// ========== 尺寸适配 ==========
QSize QmyBattery::sizeHint() const
{
    // 保持电池宽高比12:5,适配任意控件高度
    int H = this->height();
    int W = H * 12 / 5;
    return QSize(W, H);
}

// ========== 核心绘制逻辑 ==========
void QmyBattery::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event); // 标记参数未使用,消除编译器警告
    QPainter painter(this);
    // 抗锯齿,使绘制边缘更平滑
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::TextAntialiasing);

    // 1. 设置绘制坐标系(视口+窗口,固定电池比例)
    QRect rect(0, 0, width(), height());
    painter.setViewport(rect);          // 物理像素区域
    painter.setWindow(0, 0, 120, 50);   // 逻辑坐标系(120x50)

    // 2. 绘制电池背景
    QBrush brush;
    QPen pen;
    pen.setWidth(2);
    pen.setColor(mColorBorder); // 修正:mColorBoder → mColorBorder
    pen.setStyle(Qt::SolidLine);
    painter.setPen(pen);

    brush.setColor(mColorBack);
    brush.setStyle(Qt::SolidPattern);
    painter.setBrush(brush);

    // 绘制电池主体背景
    QRect batteryRect(1, 1, 109, 48);
    painter.drawRect(batteryRect);
    // 绘制电池正极(顶部小矩形)
    QRect positiveRect(110, 15, 10, 20);
    painter.drawRect(positiveRect);

    // 3. 绘制电量填充
    if (mPowerLevel > mWarnLevel)
    {
        brush.setColor(mColorPower);   // 正常电量颜色
        pen.setColor(mColorPower);
    }
    else
    {
        brush.setColor(mColorWarning); // 警告颜色
        pen.setColor(mColorWarning);
    }
    painter.setBrush(brush);
    painter.setPen(pen);

    // 电量>0时绘制填充矩形(宽度对应电量百分比)
    if (mPowerLevel > 0)
    {
        QRect powerRect(5, 5, mPowerLevel, 40);
        painter.drawRect(powerRect);
    }

    // 4. 绘制电量百分比文字(居中显示)
    QFontMetrics textSize(this->font());
    QString powStr = QString::asprintf("%d%%", mPowerLevel);
    QRect textRect = textSize.boundingRect(powStr);

    painter.setFont(this->font());
    pen.setColor(mColorBorder);
    painter.setPen(pen);
    // 文字居中计算:水平55-文字宽/2,垂直23+文字高/2
    painter.drawText(55 - textRect.width()/2, 23 + textRect.height()/2, powStr);
}

三、核心知识点解析

1. 坐标系适配(setViewport/setWindow)

通过setViewport(绑定控件物理尺寸)和setWindow(固定逻辑尺寸 120x50),实现电池控件无论拉伸 / 缩小时,始终保持 12:5 的宽高比,避免变形。

2. 绘制分层逻辑

组件绘制分为 4 层,层层叠加保证视觉效果:

  • 第 1 层:电池背景(白色 / 自定义背景色);
  • 第 2 层:电池边框 + 正极(黑色 / 自定义边框色);
  • 第 3 层:电量填充(绿色 / 红色,按阈值切换);
  • 第 4 层:电量百分比文字(居中显示,边框色保证对比度)。

3. 属性封装与 Qt 属性系统

通过Q_PROPERTY注册属性,使组件支持 Qt 属性系统:

  • 可在 UI 设计师中直接编辑电量、颜色等属性;
  • 支持信号与槽联动,如powerLevelChanged信号可绑定到其他组件响应电量变化。

4. 尺寸适配(sizeHint)

重写sizeHint返回按 12:5 比例计算的推荐尺寸,布局管理器(如 QVBoxLayout、QHBoxLayout)会优先使用该尺寸,保证组件布局协调。

四、组件使用示例

实现了QmyBattery类之后,若是用代码创建QmyBattery类对象,其使用与一般的组件类是一样的,若是在UI设计器中使用QmyBattery,则需要采用提升法,在窗体上放置一个QWidget类组件,然后鼠标右键调出菜单"提升为..."

在基类名称下选择QWidget,将提升后的类名称设置为QmyBattery,单击Add ,单击Promote,提升后在属性将组件名称修改为qmyBattery

再放置4个按钮用来测试这个电池组件。

cpp 复制代码
void MainWindow::on_pushButton_clicked()
{
    ui->qmyBattery->setPowerLevel(70);
}

void MainWindow::on_pushButton_2_clicked()
{
     ui->qmyBattery->setPowerLevel(10);
}

void MainWindow::on_pushButton_3_clicked()
{
    ui->qmyBattery->setPowerLevel(100);
}

void MainWindow::on_pushButton_4_clicked()
{
    ui->qmyBattery->setPowerLevel(0);
}

默认电量60%

设置电量100%

设置电量70%

设置电量10%

设置电量0

完整的代码下载地址:Qt中自定义QmyBattery电池组件开发代码资源-CSDN下载

总结

QmyBattery组件通过子类化QWidget,重写paintEvent实现核心绘制逻辑,封装属性与信号保证组件的可复用性和交互性。核心要点包括:

  1. 利用 Qt 绘图框架实现分层绘制,保证视觉层次清晰;
  2. 通过坐标系适配和sizeHint实现组件尺寸自适应;
  3. 遵循 Qt 属性系统设计规范,提升组件易用性;
  4. 核心逻辑解耦(绘制 / 属性 / 信号分离),便于扩展维护。

该组件可直接集成到 Qt 项目中,适用于电量显示、设备状态监控等场景,是 Qt 自定义 Widget 开发的典型实践。

相关推荐
Dxy12393102161 小时前
Python的PIL如何转Base64字符串:完整指南
开发语言·python
驰羽1 小时前
如何给Windows添加右键菜单选项
windows
Howrun7771 小时前
Linux_C++_日志实例
linux·运维·c++
头发还没掉光光1 小时前
C语言贪吃蛇:基于Linux中ncurses库实的贪吃蛇小游戏
linux·c语言·开发语言
fie88891 小时前
基于MATLAB的时变Copula实现方案
开发语言·matlab
冬奇Lab1 小时前
【Kotlin系列12】函数式编程在Kotlin中的实践:从Lambda到函数组合的优雅之旅
android·开发语言·kotlin
写代码的【黑咖啡】2 小时前
Python中的Msgpack:高效二进制序列化库
开发语言·python
梵尔纳多2 小时前
第一个 3D 图像
c++·图形渲染·opengl
Jaxson Lin2 小时前
Java编程进阶:线程基础与实现方式全解析
java·开发语言