zoukankan      html  css  js  c++  java
  • PyQt5实现虚拟摇杆

    PyQt5实现虚拟摇杆

    效果如下:

    代码如下:

    from PyQt5.QtWidgets import QWidget
    from PyQt5.QtGui import (
        QColor, QPainterPath, QFont, QPainter, QLinearGradient, QBrush, QPen, QFontMetrics,
        QRadialGradient, QPixmap, QTransform
    )
    from PyQt5.QtCore import QPoint, QRectF
    from PyQt5.Qt import Qt
    import math
    
    
    class CustomButton(QWidget):
        def __init__(self, parent=None):
            super(CustomButton, self).__init__(parent)
            self.m_pressIndex = 0
            self.m_enterIndex = 0
            self.m_isMouseEntered = False
            self.m_isMousePressed = False
            self.m_radius = 80
            self.m_arcLength = 55
            self.mCenterRound = QPoint(0, 0)
            self.m_bTextModeEn = False
            self.setMouseTracking(True)
            self.mSectorColor = QColor(38, 38, 38)
            self.m_arcPathList = []
            self.m_colorList = []
            self.m_textPathList = []
            self.mCurWorkRegion = []
            self.QUADRANT_UP = 1
            self.QUADRANT_LEFT = 2
            self.QUADRANT_DOWN = 3
            self.QUADRANT_RIGHT = 4
            self.M_PI = 3.14159265358979323846
    
            self.initButton()
            self.setWidgetStyle("Dark")
            self.setAxesVertical(False)
    
        def setWidgetStyle(self, style):
            if (style == "Bright"):
                self.mSectorColor = QColor(238, 241, 240)
                self.colorSPL = QColor(63, 155, 178)
                self.colorBKG = QColor(193, 199, 209)
    
                self.colorSectorUp2 = QColor(240, 243, 208)
                self.colorSectorUp = QColor(239, 242, 247)
                self.colorSectorDown = QColor(221, 225, 231)
    
                self.colorbgGradient0 = QColor(175, 180, 191)
                self.colorbgGradient1 = QColor(239, 242, 247)
    
                self.colorExcircle0 = QColor(211, 215, 223)
                self.colorExcircle5 = QColor(231, 235, 240)
                self.colorExcircle9 = QColor(182, 187, 197)
                self.colorInnerCircle0 = QColor(45, 48, 56)
                self.colorInnerCircle9 = QColor(30, 32, 37)
            else:
                self.mSectorColor = QColor(38, 38, 38)
                self.colorSPL = QColor(32, 149, 216)
                self.colorBKG = QColor(41, 44, 50)
    
                self.colorSectorUp2 = QColor(68, 68, 68)
                self.colorSectorUp = QColor(60, 60, 60)
                self.colorSectorDown = QColor(22, 22, 22)
    
                self.colorbgGradient0 = QColor(24, 24, 24)
                self.colorbgGradient1 = QColor(53, 57, 63)
    
                self.colorExcircle0 = QColor(68, 68, 68)
                self.colorExcircle5 = QColor(37, 40, 46)
                self.colorExcircle9 = QColor(22, 22, 22)
                self.colorInnerCircle0 = QColor(45, 48, 56)
                self.colorInnerCircle9 = QColor(30, 32, 37)
            self.update()
    
        def setRadiusValue(self, radius):
            self.m_radius = radius
    
        def setArcLength(self, arcLength):
            self.m_arcLength = arcLength
    
        def drawRotatedText(self, painter, degrees, x, y, text):
            painter.save()  # 保存原来坐标系统
            painter.translate(x, y)  # 平移坐标原点到x, y
            painter.rotate(degrees)  # 坐标旋转degrees度
            painter.drawText(0, 0, text)  # 在原点绘制文本
            painter.restore()  # 回复原来的坐标系统
    
        def setAxesVertical(self, axesVertical):
            self.mAxesVertical = axesVertical
            if (self.mAxesVertical == False):
                self.addArc(1, 0, 45, 90, self.mSectorColor)
                self.addArc(0, 1, 135, 90, self.mSectorColor)
                self.addArc(-1, 0, 225, 90, self.mSectorColor)
                self.addArc(0, -1, 315, 90, self.mSectorColor)
            else:
                self.addArc(1, 0, 0, 90, self.mSectorColor)
                self.addArc(0, 1, 90, 90, self.mSectorColor)
                self.addArc(-1, 0, 180, 90, self.mSectorColor)
                self.addArc(0, -1, 270, 90, self.mSectorColor)
    
            # 绘制中心圆
            self.centerRoundPath = QPainterPath()
            self.centerRoundPath.addEllipse(QPoint(0, 0), self.m_radius - self.m_arcLength + 2,
                                            self.m_radius - self.m_arcLength + 2)
            self.m_arcPathList.append(self.centerRoundPath)
            self.m_colorList.append(QColor(255, 255, 255))
    
            # 添加文字
            self.font = QFont()
            self.font.setFamily("Microsoft YaHei")
            self.font.setPointSize(14)
    
            for i in range(len(self.m_arcPathList)):
                painterPath = QPainterPath()
                self.m_textPathList.append(painterPath)
    
            self.mStrUp = "前"
            self.mStrLeft = "左"
            self.mStrDown = "后"
            self.mStrRight = "右"
            self.update()
    
        def initButton(self):
            self.addArc(1, 0, 45, 90, self.mSectorColor)
            self.addArc(0, 1, 135, 90, self.mSectorColor)
            self.addArc(-1, 0, 225, 90, self.mSectorColor)
            self.addArc(0, -1, 315, 90, self.mSectorColor)
    
            # 绘制中心圆
            self.centerRoundPath = QPainterPath()
            self.centerRoundPath.addEllipse(QPoint(0, 0), self.m_radius - self.m_arcLength + 2,
                                            self.m_radius - self.m_arcLength + 2)
            self.m_arcPathList.append(self.centerRoundPath)
            self.m_colorList.append(QColor(255, 255, 255))
    
            # 添加文字
            font = QFont()
            font.setFamily("Microsoft YaHei")
            font.setPointSize(14)
    
            for i in range(len(self.m_arcPathList)):
                painterPath = QPainterPath()
                self.m_textPathList.append(painterPath)
    
            self.mStrUp = "前"
            self.mStrLeft = "左"
            self.mStrDown = "后"
            self.mStrRight = "右"
    
        def paintEvent(self, QPaintEvent):
            painter = QPainter(self)
            painter.setRenderHint(QPainter.HighQualityAntialiasing, True)
    
            painter.setPen(Qt.NoPen)
            painter.translate(self.width() >> 1, self.height() >> 1)
    
            # 背景色,分割线颜色
            painter.setBrush(self.colorBKG)
            painter.drawEllipse(QPoint(0, 0), self.m_radius + 8, self.m_radius + 8)
    
            linearGradient = QLinearGradient(0, -self.m_radius - 2, 0, self.m_radius + 2)
            linearGradient.setColorAt(0.0, self.colorSectorUp2)
            linearGradient.setColorAt(0.9, self.colorSectorDown)
            painter.setBrush(QBrush(linearGradient))
            painter.drawEllipse(QPoint(0, 0), self.m_radius + 2, self.m_radius + 2)
    
            linearGradient = QLinearGradient(0, -self.m_radius, 0, self.m_radius)
            linearGradient.setColorAt(0.0, self.colorSectorUp)
            linearGradient.setColorAt(0.9, self.colorSectorDown)
            painter.setBrush(QBrush(linearGradient))
            painter.drawEllipse(QPoint(0, 0), self.m_radius, self.m_radius)
    
            bgGradient = QLinearGradient(0, -37, 0, 37)
            bgGradient.setColorAt(0.0, self.colorbgGradient0)
            bgGradient.setColorAt(1.0, self.colorbgGradient1)
            painter.setBrush(bgGradient)
            painter.drawEllipse(QPoint(0, 0), self.m_radius - self.m_arcLength + 4,
                                self.m_radius - self.m_arcLength + 4)
    
            count = 4
            for i in range(count):
                painter.save()
                if (self.mAxesVertical == False):
                    painter.rotate(45 + 90 * i)
    
                else:
                    painter.rotate(0 + 90 * i)
                painter.setPen(QPen(self.colorBKG, 3, Qt.SolidLine))
                painter.drawLine(0, self.m_radius - self.m_arcLength + 5, 0, self.m_radius + 5)
                painter.setPen(QPen(self.colorSPL, 3, Qt.SolidLine, Qt.RoundCap))
                painter.drawLine(0, self.m_radius - self.m_arcLength + 6, 0, 40)
                painter.setPen(QPen(self.colorSPL, 3, Qt.SolidLine))
                painter.drawLine(0, 40, 0, self.m_radius - 5)
                painter.restore()
    
            linearGradient = QLinearGradient(0, self.mCenterRound.y() - self.m_radius + self.m_arcLength - 1, 0,
                                             self.mCenterRound.y() + self.m_radius - self.m_arcLength + 1)
            linearGradient.setColorAt(0.0, self.colorExcircle0)
            linearGradient.setColorAt(0.0, self.colorExcircle5)
            linearGradient.setColorAt(0.9, self.colorExcircle9)
    
            painter.setBrush(QBrush(linearGradient))
            painter.drawEllipse(self.mCenterRound, self.m_radius - self.m_arcLength, self.m_radius - self.m_arcLength)
    
            painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
    
            if self.mAxesVertical == False:
                leftmatrix = QTransform()
                if (self.QUADRANT_UP in self.mCurWorkRegion):
                    painter.drawPixmap(-30, -60, 60, 30, self.mDegreePixmap_y)
                    leftmatrix.reset()
                if (self.QUADRANT_LEFT in self.mCurWorkRegion):
                    leftmatrix.rotate(270)
                    mDegreePixmap = self.mDegreePixmap_x.transformed(leftmatrix, Qt.SmoothTransformation)
                    painter.drawPixmap(-60, -30, 30, 60, mDegreePixmap)
                    leftmatrix.reset()
                if (self.QUADRANT_DOWN in self.mCurWorkRegion):
                    leftmatrix.rotate(180)
                    mDegreePixmap = self.mDegreePixmap_y.transformed(leftmatrix, Qt.SmoothTransformation)
                    painter.drawPixmap(-30, 30, 60, 30, mDegreePixmap)
                    leftmatrix.reset()
                if (self.QUADRANT_RIGHT in self.mCurWorkRegion):
                    leftmatrix.rotate(90)
                    mDegreePixmap = self.mDegreePixmap_x.transformed(leftmatrix, Qt.SmoothTransformation)
                    painter.drawPixmap(30, -30, 30, 60, mDegreePixmap)
                    leftmatrix.reset()
    
            font = QFont()
            font.setFamily("Microsoft YaHei")
            font.setPointSize(12)
            painter.setFont(font)
            painter.setPen(QColor(170, 170, 170))
            if self.mAxesVertical == True:
                painter.drawText(QPoint(-60, -40), self.mStrUp)
                painter.drawText(QPoint(30, -40), self.mStrLeft)
    
                painter.drawText(QPoint(-80, 40), self.mStrDown)
                painter.drawText(QPoint(20, 40), self.mStrRight)
            else:
    
                fm = QFontMetrics(font)
                rText = 65
                nHeight = fm.height() - 4
                iTotalWidth = fm.width(self.mStrUp)
                painter.save()
                painter.rotate(-90 * iTotalWidth / (rText * self.M_PI))
                for i in range(len(self.mStrUp)):
                    self.nWidth = fm.width(self.mStrUp[i])
                    painter.rotate(90 * self.nWidth / (rText * self.M_PI))
                    painter.drawText(-self.nWidth / 2, -1 * rText, self.mStrUp[i])
                    painter.rotate(90 * self.nWidth / (rText * self.M_PI))
                painter.restore()
                painter.save()
                if (self.m_bTextModeEn):
    
                    iTotalWidth = fm.width(self.mStrRight)
                    painter.rotate(90 - 90 * iTotalWidth / (rText * self.M_PI))
                    for i in range(len(self.mStrRight)):
                        nWidth = fm.width(self.mStrRight[i])
                        painter.rotate(90 * nWidth / (rText * self.M_PI))
                        painter.drawText(-nWidth / 2, -1 * rText, self.mStrRight[i])
                        painter.rotate(90 * nWidth / (rText * self.M_PI))
                else:
                    iTotalWidth = nHeight * len(self.mStrRight)
                    painter.rotate(-90 * iTotalWidth / (rText * self.M_PI))
                    for i in range(len(self.mStrRight)):
                        painter.rotate(90 * nHeight / (rText * self.M_PI))
                        painter.drawText(rText - 5, nHeight / 2, self.mStrRight[i])
                        painter.rotate(90 * nHeight / (rText * self.M_PI))
                painter.restore()
    
                painter.save()
                iTotalWidth = fm.width(self.mStrDown)
                painter.rotate(90 * iTotalWidth / (rText * self.M_PI))
                for i in range(len(self.mStrDown)):
                    nWidth = fm.width(self.mStrDown[i])
                    painter.rotate(-90 * nWidth / (rText * self.M_PI))
                    painter.drawText(-nWidth / 2, rText + nHeight - 8, self.mStrDown[i])
                    painter.rotate(-90 * nWidth / (rText * self.M_PI))
                painter.restore()
    
                painter.save()
                if (self.m_bTextModeEn):
                    iTotalWidth = fm.width(self.mStrLeft)
                    painter.rotate(90 + 90 * iTotalWidth / (rText * self.M_PI))
                    for i in range(len(self.mStrLeft)):
                        nWidth = fm.width(self.mStrLeft[i])
                        painter.rotate(-90 * nWidth / (rText * self.M_PI))
                        painter.drawText(-nWidth / 2, rText + nHeight - 8, self.mStrLeft[i])
                        painter.rotate(-90 * nWidth / (rText * self.M_PI))
    
                else:
                    iTotalWidth = nHeight * len(self.mStrLeft)
                    painter.rotate(90 * iTotalWidth / (rText * self.M_PI))
                    for i in range(len(self.mStrLeft)):
                        painter.rotate(-90 * nHeight / (rText * self.M_PI))
                        painter.drawText(-rText - 10, nHeight / 2, self.mStrLeft[i])
                        painter.rotate(-90 * nHeight / (rText * self.M_PI))
                painter.restore()
    
        def addArc(self, x, y, startAngle, angleLength, color):
            rect = QRectF(-self.m_radius + x, -self.m_radius + y, self.m_radius * 2, self.m_radius * 2)
            path = QPainterPath()
            path.arcTo(rect, startAngle, angleLength)
            subPath = QPainterPath()
            subPath.addEllipse(rect.adjusted(self.m_arcLength, self.m_arcLength, -self.m_arcLength, -self.m_arcLength))
            path -= subPath
            self.m_arcPathList.append(path)
            radialGradient = QRadialGradient()
            radialGradient.setCenter(0, 0)
            radialGradient.setRadius(self.m_radius)
            radialGradient.setColorAt(0, color)
            radialGradient.setColorAt(1.0, color)
            self.m_colorList.append(radialGradient)
    
        def mousePressEvent(self, event):
            mousePressPoint = event.pos()
            translatePoint = mousePressPoint - QPoint(self.width() >> 1, self.height() >> 1)
            for i in range(len(self.m_arcPathList)):
                if (self.m_arcPathList[i].contains(translatePoint) or self.m_textPathList[i].contains(translatePoint)):
                    self.m_pressIndex = i
                    self.m_isMousePressed = True
                    self.update()
                    break
    
        def mouseReleaseEvent(self, event):
            if (self.m_isMousePressed):
                self.m_isMousePressed = False
                self.mCenterRound = QPoint(0, 0)
                self.mDegreePixmap_x = QPixmap(0, 0)
                self.mDegreePixmap_y = QPixmap(0, 0)
                self.update()
    
        def mouseMoveEvent(self, event):
            if (self.m_isMousePressed):
                point = event.pos() - QPoint(self.width() >> 1, self.height() >> 1)
                x = point.x()
                y = -point.y()
                if y >= 85:
                    y = 85
                elif y <= -85:
                    y = -85
                if x >= 85:
                    x = 85
                elif x <= -85:
                    x = -85
                if x * x + y * y > 85 * 85:
                    x_y = abs(x) / abs(y)
                    _y = 85 / math.sqrt(x_y * x_y + 1.0)
                    _x = x_y * _y
                    if y >= 0:
                        y = abs(_y)
                    else:
                        y = -abs(_y)
                    if x >= 0:
                        x = abs(_x)
                    else:
                        x = -abs(_x)
                self.mCenterRound = QPoint(x, -y)
                angle = self.analysisAngle(x, y)
                if angle >= 90 and angle <= 180:
                    self.mCurWorkRegion = [self.QUADRANT_UP, self.QUADRANT_LEFT]
                elif angle > 0 and angle <= 90:
                    self.mCurWorkRegion = [self.QUADRANT_UP, self.QUADRANT_RIGHT]
                elif angle > 180 and angle <= 270:
                    self.mCurWorkRegion = [self.QUADRANT_DOWN, self.QUADRANT_LEFT]
                elif angle > 270 and angle < 360:
                    self.mCurWorkRegion = [self.QUADRANT_DOWN, self.QUADRANT_RIGHT]
                self.mDegreePixmap_x = self.getPixmap(abs(x))
                self.mDegreePixmap_y = self.getPixmap(abs(y))
                self.update()
    
        def analysisAngle(self, x, y):
            angle = math.atan2(abs(y), abs(x)) / (2 * math.acos(-1)) * 360
            if (x < 0 and y > 0):
                angle = 180 - angle
            if (x < 0 and y < 0):
                angle += 180
            if (x > 0 and y < 0):
                angle = 360 - angle
            return angle
    
        def getPixmap(self, ping):
            return self.getSignalPixmap(QColor(0x5, 0x00c7, 0xc7), self.getLineNum(ping))
    
        def getColor(self, ping):
            if (ping <= 10):
                return QColor(0xea, 0x00, 0x00)
            elif (ping <= 20):
                return QColor(0xff, 0x00, 0x80)
            elif (ping <= 30):
                return QColor(0xe8, 0x00, 0xe8)
            elif (ping <= 40):
                return QColor(0xea, 0xc1, 0x00)
            elif (ping <= 50):
                return QColor(0xe1, 0xe1, 0x00)
            elif (ping <= 60):
                return QColor(0x9a, 0xff, 0x02)
            elif (ping <= 70):
                return QColor(0x00, 0xff, 0xff)
            elif (ping <= 80):
                return QColor(0x28, 0x94, 0xff)
            else:
                return QColor(0x6a, 0x6a, 0xff)
    
        def getLineNum(self, ping):
            if (ping <= 20):
                return 1
            elif (ping <= 40):
                return 2
            elif (ping <= 60):
                return 3
            elif (ping <= 80):
                return 4
            else:
                return 5
    
        def getSignalPixmap(self, color, linenum):
    
            pixmap = QPixmap(60, 30)
            pixmap.fill(QColor(255, 255, 255, 0))
    
            painter = QPainter(pixmap)
            painter.setRenderHint(QPainter.HighQualityAntialiasing, True)
            painter.setPen(QPen(color, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
            i = 1
            xpos = 0
            while i <= linenum:
                painter.drawArc(30 - i * 6, 30 - i * 5, i * 12, i * 10, 53 * 16, 37 * 2 * 16)
                i += 1
                xpos += 1
            return pixmap
    
    
    if __name__ == '__main__':
        import sys
        from PyQt5.QtWidgets import QApplication
    
        app = QApplication(sys.argv)
        mainWindow = CustomButton()
        mainWindow.show()
        sys.exit(app.exec_())
    

    有用的话请点赞.

  • 相关阅读:
    bzoj 2816: [ZJOI2012]网络 (LCT 建多棵树)
    bzoj 2157: 旅游 (LCT 边权)
    bzoj 3669: [Noi2014]魔法森林 (LCT)
    bzoj 2049: [Sdoi2008]Cave 洞穴勘测 (LCT)
    bzoj 2002 : [Hnoi2010]Bounce 弹飞绵羊 (LCT)
    bzoj 3282: Tree (Link Cut Tree)
    模拟赛1
    Some tricks
    模拟赛简要题解与心得
    Noip 训练指南
  • 原文地址:https://www.cnblogs.com/zyyhxbs/p/12834433.html
Copyright © 2011-2022 走看看