前言:一般电池检测系统都会涉及到电池控件,电池控件用于显示电池的各项指标参数。学习如何使用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(): 绘制一个矩形。


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", "电池充电"))
806

被折叠的 条评论
为什么被折叠?



