PYQT5 Qpainter绘制仪表盘

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_())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值