PyQt5如何绘制电池控件

部署运行你感兴趣的模型镜像

前言:一般电池检测系统都会涉及到电池控件,电池控件用于显示电池的各项指标参数。学习如何使用pyqt5实现绘制电池控件。

1. 上位机界面效果展示

通过学习如何使用pyqt5实现绘制电池控件,想要实现以下界面。

在这里插入图片描述

自己使用PyQt5制作的界面效果如下:

在这里插入图片描述

2. pyqt5如何绘制电池控件

参考文章:Qt自定义控件之Battery电池控件

上述文章是通过C++代码实现的电池控件的绘制,参考该文章思路,转成python语言绘制电池控件。

电池控件样式如下:

在这里插入图片描述

电池控件生成代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : Logintern09
import sys
from PyQt5.QtCore import QRectF, QPoint, Qt, QRect
from PyQt5.QtGui import QPainter, QColor, QPen, QFont
from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow, QVBoxLayout


class BasicBattery(QWidget):

    def __init__(self, parent=None):
        super(BasicBattery, self).__init__(parent)

        # 枚举类型定义了电池状态
        self.BatteryStatus = {
            "Discharging": "放电状态",
            "Charging": "充电状态",
            "Full": "充满状态",
        }
        self.x_position = 20  # 电池x轴位置
        self.y_position = 20  # 电池y轴位置
        self.width_percent = 0.80  # 电池宽度占整个界面宽度百分比
        self.height_percent = 0.80  # 电池高度占整个界面宽度百分比
        self.m_min_value = 0
        self.m_max_value = 100
        self.m_level = 80  # 电量值
        self.m_round = True  # 标志变量,表示电池外形是否为圆角
        self.m_roundPresent = 5  # 圆角占电池高度的百分比,用于控制圆角的大小
        self.m_status = "Charging"  # 电池状态
        self.m_border = QColor("black")  # 电池边框颜色
        self.line_width = 3  # 电池边框线条宽度
        self.m_padding = QColor("green")  # 电池内部填充颜色
        self.m_charge = QColor("green")  # 充电指示器颜色
        self.m_nobattery = QColor("red")  # 低电量警告颜色
        self.m_offset = QPoint(2, 2)  # 绘制偏移量,用于绘制电量指示器位置
        self.value_text_color = QColor("white")  # 电池电量显示文本的字体颜色

    def getSize(self):
        self.m_width = self.width()  # 电池宽度
        self.m_height = self.height()  # 电池高度

    def paintEvent(self, event):
        pass

    def resizeEvent(self, event):
        self.getSize()
        self.update()

    def setMaxValue(self, m_max_value):
        self.m_max_value = m_max_value
        self.update()

    def getMaxValue(self):
        return self.m_max_value

    def setMinValue(self, m_min_value):
        self.m_min_value = m_min_value
        self.update()

    def getMinValue(self):
        return self.m_min_value

    def setValueRange(self, m_min_value, m_max_value):
        self.m_min_value = m_min_value
        self.m_max_value = m_max_value
        self.update()

    def getValueRange(self):
        return self.m_min_value, self.m_max_value

    def setValueTextColor(self, color):
        self.value_text_color = color
        self.update()

    def getValueTextColor(self):
        return self.value_text_color

    # 设置电量值
    def setLevel(self, level):
        self.m_level = level
        self.update()

    # 获取电量值
    def getLevel(self):
        return self.m_level

    # 设置电池状态
    def setStatus(self, status: str):
        self.m_status = status
        self.update()

    # 获取电池状态
    def getStatus(self):
        return self.m_status

    # 设置电池边框颜色
    def setBorderColor(self, color):
        self.m_border = color
        self.update()

    # 获取电池边框颜色
    def getBorderColor(self):
        return self.m_border

    # 设置电池内部填充颜色
    def setPaddingColor(self, color):
        self.m_padding = color
        self.update()

    # 获取电池内部填充颜色
    def getPaddingColor(self):
        return self.m_padding

    # 设置充电指示器颜色
    def setChargeColor(self, color):
        self.m_charge = color
        self.update()

    # 获取充电指示器颜色
    def getChargeColor(self):
        return self.m_charge

    # 设置低电量警告颜色
    def setLowBatteryColor(self, color):
        self.m_nobattery = color
        self.update()

    # 获取低电量警告颜色
    def getLowBatteryColor(self):
        return self.m_nobattery

    # 设置绘制偏移量
    def setOffset(self, offset):
        self.m_offset = offset
        self.update()

    # 获取绘制偏移量
    def getOffset(self):
        return self.m_offset

    # 设置电池外形是否为圆角
    def setRound(self, round):
        self.m_round = round
        self.update()

    # 获取电池外形是否为圆角
    def isRound(self):
        return self.m_round

    # 设置圆角占电池高度的百分比
    def setRoundPresent(self, roundPresent):
        self.m_roundPresent = roundPresent
        self.update()

    # 获取圆角占电池高度的百分比
    def getRoundPresent(self):
        return self.m_roundPresent


class QBattery(BasicBattery):
    def __init__(self, parent=None):
        super(QBattery, self).__init__(parent)
        self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setFixedSize(100, 200)

    def paintEvent(self, event):
        super(QBattery, self).paintEvent(event)
        self.drawBorder()
        self.drawFill()
        self.setText()

    # 绘制电池边框
    def drawBorder(self):
        painter = QPainter(self)
        # 保存当前画笔状态
        painter.save()

        # 设置画笔颜色和样式
        painter.setPen(QPen(self.m_border, self.line_width))

        # 绘制电池外壳,采用圆角矩形
        self.RoundedRect_width = self.m_width * self.width_percent
        self.RoundedRect_height = self.m_height * self.height_percent
        painter.drawRoundedRect(
            self.x_position,
            self.y_position,
            self.RoundedRect_width,
            self.RoundedRect_height,
            self.m_roundPresent,
            self.m_roundPresent,
        )

        # 计算并绘制电池上侧的正极
        poleWidth = self.RoundedRect_width * 0.3  # 正极宽度
        poleHeight = 5  # 正极高度
        poleX = (
            self.x_position + (self.RoundedRect_width - poleWidth) / 2
        )  # 正极横坐标,位于电池上侧边框处并考虑间隔
        poleY = self.y_position - poleHeight  # 正极纵坐标,使其垂直居中

        # 设置正极颜色与边框颜色一致,并绘制正极
        painter.setBrush(self.m_border)
        painter.drawRect(poleX, poleY, poleWidth, poleHeight)

        # 恢复之前保存的画笔状态
        painter.restore()

    # 绘制电池填充
    def drawFill(self):
        painter = QPainter(self)
        painter.save()

        # 根据电池状态设置填充颜色
        fillColor = self.m_padding
        if self.m_status == "Charging":
            fillColor = self.m_charge
        elif self.m_status == "Full":
            self.m_level = self.m_max_value
        elif (
            self.m_level
            <= self.m_min_value + (self.m_max_value - self.m_min_value) * 0.2
        ):  # 电池电量少于20%低电量报警
            fillColor = self.m_nobattery
        # 设置填充颜色
        painter.setBrush(fillColor)

        # 计算电池电量范围占整个电池高度的单位比
        self.m_value_percent = float(
            self.RoundedRect_height / (self.m_max_value - self.m_min_value)
        )
        # 计算电池内部填充区域的起始点
        fillX = self.x_position + self.m_offset.x()
        fillY = (
            self.y_position
            + self.RoundedRect_height
            - (self.m_level * self.m_value_percent)
            + self.m_offset.y()
        )

        # 计算电池内部填充区域的宽度
        fillWidth = self.RoundedRect_width * 0.95

        # 计算电池内部填充区域的高度
        fillHeight = self.y_position + self.RoundedRect_height - fillY

        # 绘制填充区域
        painter.drawRoundedRect(
            QRectF(fillX, fillY, fillWidth, fillHeight),
            self.m_roundPresent,
            self.m_roundPresent,
        )
        painter.restore()

    def setText(self):
        painter = QPainter(self)
        painter.save()
        painter.setPen(self.value_text_color)
        painter.setFont(QFont("Arial", 12))
        painter.drawText(
            QRect(
                int(self.x_position) + self.RoundedRect_width * 0.2,
                self.y_position
                + (self.m_max_value - self.m_level) * self.m_value_percent
                + 10,
                50,
                20,
            ),
            Qt.AlignCenter,
            f"{self.m_level}",
        )
        painter.restore()


def main():
    app = QApplication(sys.argv)
    window = QMainWindow()
    window.setGeometry(100, 100, 100, 290)
    window.setWindowTitle("Battery Example")
    Battery = QBattery()
    layout = QVBoxLayout()
    layout.addWidget(Battery)
    window.setCentralWidget(QWidget())
    window.centralWidget().setLayout(layout)
    window.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    # main()
    app = QApplication([])
    widget = QBattery()
    widget.show()
    app.exec_()

2.1 pyqt5中painter.drawRoundedRect用法

在PyQt5中,QPainter 类提供了 drawRoundedRect() 方法,该方法用于绘制一个带有圆角的矩形。

在这里插入图片描述

drawRoundedRect() 方法的基本语法如下:

QPainter.drawRoundedRect(self, rect, xRadius, yRadius, style=Qt.SolidLine)
其中:

rect 是要绘制的矩形的位置和大小。

xRadius 和 yRadius 分别指定了椭圆的宽度和高度,用于创建圆角。

style 参数定义了矩形边界的样式,默认为 Qt.SolidLine,表示实线。

下面是一个简单的例子,演示如何在一个 QWidget 上绘制一个带有圆角的矩形:

from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtCore import Qt
 
class RoundedRectWidget(QWidget):
    def __init__(self):
        super().__init__()
 
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setPen(QPen(Qt.blue, 3))
        painter.drawRoundedRect(10, 10, 100, 50, 10, 10)
 
 
app = QApplication([])
widget = RoundedRectWidget()
widget.show()
app.exec_()

在这个例子中,我们创建了一个 RoundedRectWidget 类,它继承自 QWidget。在 paintEvent() 方法中,我们使用 QPainter 创建了一个带有水平和垂直半径均为 10 的圆角矩形。矩形的位置是从窗口的左上角开始,向右下方偏移 10 个像素,大小是 100x50 像素。矩形的边界线宽度为 3 像素,颜色为蓝色。

2.2 pyqt5中painter.drawRect用法

drawRect(): 绘制一个矩形。

在这里插入图片描述

实战PyQt5: 123-详解QPainter绘图

在这里插入图片描述

2.3 pyqt5中painter.drawText用法

painter.drawText() 绘制文本

painter.drawText()方法,需要说明其中的第一个参数:

painter.drawText(event.rect(), Qt.AlignCenter, self.text)
第一个参数是指定的绘图区域,此处的event.rect()指的是主事件的矩形区域,也就是整个主窗口,除此之外,可以通过指定x和y来指定绘图区域,下面截图的代码示例就是通过指定x和y来指定绘图区域。

python示例代码如下:

在这里插入图片描述

3. 程序实现完整代码

main.py代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : Logintern09


import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
from PyQt5.QtGui import QPixmap, QFont, QColor, QIcon
from PyQt5.QtCore import Qt
from battery_view import Ui_MainWindow
from QBattery import QBattery


class mainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self):
        super(mainWindow, self).__init__()
        self.setupUi(self)  # 初始化窗口

        # 设置窗口图标
        self.setWindowIcon(QIcon("./icon/电量未知.png"))
        # 设置Frame尺寸
        self.frame.setFixedSize(850, 300)
        self.frame_2.setFixedSize(850, 300)
        label = QLabel()
        label.setPixmap(QPixmap("./icon/手机.png"))
        self.gridLayout.addWidget(label, 0, 0, 1, 1)
        label = QLabel()
        label.setPixmap(QPixmap("./icon/WIFI.png"))
        self.gridLayout_2.addWidget(label, 0, 0, 1, 1)
        label = QLabel("3G call time\n(minutes)")
        self.gridLayout.addWidget(label, 0, 1, 1, 1)
        label = QLabel("3G internet\nuse (minutes)")
        self.gridLayout_2.addWidget(label, 0, 1, 1, 1)

        voltage_value = [1859, 1579, 1492, 712]
        charge_color = ["green", "orange", "orange", "brown"]
        label_data = ["HTC 10", "LG G5", "Samsung\nGalaxy S7", "Apple\niPhone 7"]
        for i in range(4):
            # 设置电池电量
            battery = QBattery()
            battery.setValueRange(0, 2000)
            battery.setLevel(voltage_value[i])
            battery.setChargeColor(QColor(charge_color[i]))
            self.gridLayout.addWidget(battery, 0, i + 2, 1, 1)
            label = QLabel(label_data[i])
            label.setAlignment(Qt.AlignCenter)  # 设置文字居中对齐
            self.gridLayout.addWidget(label, 1, i + 2, 1, 1)

        voltage_value = [790, 677, 640, 615]
        charge_color = ["green", "orange", "orange", "brown"]
        label_data = ["HTC 10", "Samsung\nGalaxy S7", "LG G5", "Apple\niPhone 7"]
        for i in range(4):
            battery = QBattery()
            battery.setValueRange(0, 2000)
            battery.setLevel(voltage_value[i])
            battery.setChargeColor(QColor(charge_color[i]))
            self.gridLayout_2.addWidget(battery, 0, i + 2, 1, 1)
            label = QLabel(label_data[i])
            label.setAlignment(Qt.AlignCenter)  # 设置文字居中对齐
            self.gridLayout_2.addWidget(label, 1, i + 2, 1, 1)

        # 找到所有的QLabel控件
        label_obj = self.findChildren(QLabel)
        for label in label_obj:
            # 设置QLabel的字体大小
            font = QFont()
            font.setPointSize(14)  # 设置字体大小为14点
            font.setBold(True)
            label.setFont(font)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    ui = mainWindow()
    ui.show()
    sys.exit(app.exec_())

Qt Designer工具生成初始界面布局.ui转成.py代码如下:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'battery_view.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(850, 584)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout_3 = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.frame = QtWidgets.QFrame(self.centralwidget)
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.gridLayout_5 = QtWidgets.QGridLayout(self.frame)
        self.gridLayout_5.setObjectName("gridLayout_5")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        self.gridLayout.setHorizontalSpacing(10)
        self.gridLayout.setVerticalSpacing(0)
        self.gridLayout.setObjectName("gridLayout")
        self.gridLayout_5.addLayout(self.gridLayout, 0, 0, 1, 1)
        self.gridLayout_3.addWidget(self.frame, 0, 0, 1, 1)
        self.frame_2 = QtWidgets.QFrame(self.centralwidget)
        self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_2.setObjectName("frame_2")
        self.gridLayout_4 = QtWidgets.QGridLayout(self.frame_2)
        self.gridLayout_4.setObjectName("gridLayout_4")
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        self.gridLayout_2.setHorizontalSpacing(10)
        self.gridLayout_2.setVerticalSpacing(0)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.gridLayout_4.addLayout(self.gridLayout_2, 0, 0, 1, 1)
        self.gridLayout_3.addWidget(self.frame_2, 1, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "电池充电"))

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

草莓仙生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值