import math
import sys
from PyQt5.QtGui import QFont, QPainter, QColor, QPolygon, QRadialGradient, QPen
from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtWidgets import QApplication, QLabel
class ChartWidget(QLabel):
def __init__(self):
super().__init__()
self.radius = self.height() // 4 # 半径
self.setMinimumSize(800,400)
self.pieColorStart = QColor(127, 255, 0) # 绿色
self.pieColorStart2 = QColor(50, 235, 50) # 绿色
self.pieColorMid = QColor(255, 255, 0) # 黄色色
self.pieColorMid2 = QColor(255, 115, 0) # 橙色
# self.pieColorEnd2 = QColor(230, 84, 0) # 深橙色
self.pieColorEnd = QColor(139, 0, 0) # 红色
self.pointerColor = QColor(66, 66, 66) # 青色
self.startAngle = 90 # 设置扇形的角度,这里是一个半圆
self.endAngle = 90
self.minValue = 0
self.maxValue = 100
self.scaleMajor = 5 # 分为几个主刻度
self.font = QFont("宋体", 20)
self.font.setBold(True) # 粗体
self.setStyleSheet("border:3px solid grey")
def paintEvent(self, event):
width = self.width()
height = self.height()
painter = QPainter(self) # 初始化painter
painter.translate(width // 2, height//3*2) # 坐标轴变换,调用translate()将坐标原点平移至窗口中心
painter.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing)
painter.setFont(self.font)
painter.setPen(QColor(26, 95, 95))
self.drawColorPie(painter) # 画饼
self.drawPointerIndicator(painter, 40) # 画指针
self.drawText(painter) # 画刻度数值
self.drawLine(painter) # 画刻度线
def drawColorPie(self, painter): # 绘制三色环
painter.save() # save()保存当前坐标系
width = self.width()
height = self.height()
min_size = min(width, height)
self.radius = min_size //2 # 半径
radius = self.radius
painter.setPen(Qt.NoPen)
rect = QRectF(-radius, -radius, radius * 2, radius * 2) # 扇形所在圆区域
# 计算三色圆环范围角度。green:blue:red = 1:2:1
angleAll = 360 - self.startAngle - self.endAngle # self.startAngle = 45, self.endAngle = 45
angleStart = angleAll // 5 # 设置几个颜色扇形就除几
angleStart2 = angleAll // 5
angleMid = angleAll // 5
angleMid2 = angleAll // 5
angleEnd = angleAll // 5
# angleEnd2 = angleAll // 6
rg = QRadialGradient(0, 0, radius, 0, 0) # 起始圆心坐标,半径,焦点坐标
ratio = 0.8
# 绘制绿色
rg.setColorAt(0, Qt.transparent) # 透明色
rg.setColorAt(ratio, Qt.transparent)
rg.setColorAt(ratio + 0.01, self.pieColorStart)
rg.setColorAt(1, self.pieColorStart)
painter.setBrush(rg)
painter.drawPie(rect, (270 - self.startAngle - angleStart) * 16, angleStart * 16) # 270 = 360-starangle90
# 绘制深绿色
rg.setColorAt(0, Qt.transparent) # 透明色
rg.setColorAt(ratio, Qt.transparent)
rg.setColorAt(ratio + 0.01, self.pieColorStart2)
rg.setColorAt(1, self.pieColorStart2)
painter.setBrush(rg)
painter.drawPie(rect, (270 - self.startAngle - angleStart - angleStart2) * 16, angleStart2 * 16)
# 绘制黄色环
rg.setColorAt(0, Qt.transparent)
rg.setColorAt(ratio, Qt.transparent)
rg.setColorAt(ratio + 0.01, self.pieColorMid)
rg.setColorAt(1, self.pieColorMid)
painter.setBrush(rg)
painter.drawPie(rect, (270 - self.startAngle - angleStart - angleStart2 - angleMid) * 16, angleMid * 16)
# 绘制橙色色环
rg.setColorAt(0, Qt.transparent)
rg.setColorAt(ratio, Qt.transparent)
rg.setColorAt(ratio + 0.01, self.pieColorMid2)
rg.setColorAt(1, self.pieColorMid2)
painter.setBrush(rg)
painter.drawPie(rect, (270 - self.startAngle - angleStart - angleStart2 - angleMid - angleMid2) * 16,angleMid2 * 16)
# 绘制深橙色色环
# rg.setColorAt(0, Qt.transparent)
# rg.setColorAt(ratio, Qt.transparent)
# rg.setColorAt(ratio + 0.01, self.pieColorEnd2)
# rg.setColorAt(1, self.pieColorEnd2)
# painter.setBrush(rg)
# painter.drawPie(rect,(270 - self.startAngle - angleStart - angleStart2 - angleMid - angleMid2 - angleEnd2) * 16,angleEnd2 * 15)
# 绘制红色环
rg.setColorAt(0, Qt.transparent)
rg.setColorAt(ratio, Qt.transparent)
rg.setColorAt(ratio + 0.01, self.pieColorEnd)
rg.setColorAt(1, self.pieColorEnd)
painter.setBrush(rg)
painter.drawPie(rect, (270 - self.startAngle - angleStart - angleStart2 - angleMid - angleMid2 - angleEnd) * 16,angleEnd * 16)
painter.restore() # restore()恢复坐标系
def drawPointerIndicator(self, painter, currentValue):
painter.save()
# 绘制指针
radius = self.radius*0.8 # 指针长度
painter.setPen(Qt.NoPen)
painter.setBrush(self.pointerColor)
# 绘制多边形做指针
pts = QPolygon()
pts.setPoints(-5, 0, 0, -8, 5, 0, 0, radius)
# 旋转指针,使得指针起始指向为0刻度处
painter.rotate(self.startAngle)
degRotate = (360.0 - self.startAngle - self.endAngle) / (self.maxValue - self.minValue) * (currentValue - self.minValue)
painter.rotate(degRotate)
painter.drawConvexPolygon(pts)
painter.restore()
def drawLine(self, painter):
painter.save()
# 绘制刻度线
radius = self.radius
painter.rotate(self.startAngle) # self.startAngle = 90,旋转90度
steps = self.scaleMajor
angleStep = (360.0 - self.startAngle - self.endAngle) / steps # 刻度角
for i in range(steps + 1):
pen = QPen()
pen.setWidth(5)
pen.setColor(QColor(25, 0, 0))
painter.setPen(pen)
painter.drawLine(0, radius - 30, 0, radius+1)
painter.rotate(angleStep)
painter.restore()
def drawText(self, painter):
painter.save()
startRad = 3.17 # (360 - startAngle- endAngle) * (3.14 / 180)
deltaRad = 0.637 # 360 * (3.14 / 180)
radius = self.radius*1.1
offset = 5
for i in range(self.scaleMajor + 1): # self.scaleMajor = 8, 8个主刻度
# 正余弦计算
sina = math.sin(startRad - i * deltaRad)
cosa = math.cos(startRad - i * deltaRad)
# 刻度值计算
value = math.ceil((1.0 * i * ((self.maxValue - self.minValue) / self.scaleMajor) + self.minValue))
# math.ceil(x):返回不小于x的最小整数
strValue = str(int(value))
# 字符的宽度和高度
textWidth = self.fontMetrics().width(strValue)
textHeight = self.fontMetrics().height()
# 字符串的起始位置。注意考虑到字符宽度和高度进行微调
x = radius * cosa - textWidth / 2
y = -radius * sina + textHeight / 4
painter.setFont(self.font)
painter.setPen(QColor(26, 95, 95))
painter.drawText(x - offset, y-offset, strValue)
painter.restore()
if __name__ == "__main__":
app = QApplication(sys.argv)
win = ChartWidget()
win.show()
sys.exit(app.exec_())
PYQT5 Qpainter绘制仪表盘
最新推荐文章于 2024-01-29 13:36:06 发布