PyQt5 异形按钮

作者: bianruifeng | 来源:发表于2022-11-25 16:21 被阅读0次
    image.png

    代码:

    
    class UIButton(QWidget):
        btn_width = 20
        btn_height = 20
        top_margin = 10
        side_margin = 10
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            # self.pix = QBitmap("./Resources/Images/back.png")
            # print(self.pix.size())
            # self.resize(self.pix.size())
            self.setFixedSize(300, 300)
            self.outerPieRadius = 100
    
            self.mouseCenterView = False
            self.mouseBottomView = False
            self.mouseRightView = False
            self.mouseTopView = False
            self.mouseLeftView = False
    
            self.mouseOuterCream = False
            self.outerChampagnePercent = 90
    
            self.setMouseTracking(True)  # 设置鼠标自动跟踪
    
    
        def drawOuterPie(self, painter):
            """
            绘制右侧按钮
            :param painter:
            :return:
            """
            painter.save()
            # 以下绘图保存至painter的坐标系统
            # 设置标志位,判断鼠标是否进入该区域。如果进入该区域,则半径扩大
            if self.mouseRightView:
                radius1 = self.outerPieRadius + 4
            else:
                radius1 = self.outerPieRadius
    
            # 绘制大扇形
    
            rect = QtCore.QRectF(-radius1/2, -radius1/2, radius1, radius1)  # 该扇形饼圆所在的region
            pathOuterChampagnePie = QtGui.QPainterPath()  # 新建QPainterPath对象
            pathOuterChampagnePie.arcMoveTo(rect, -45)  # 画弧线的起点角度,从0°开始
            pathOuterChampagnePie.arcTo(rect, -45, 90)  # 扇形饼圆弧度为self.outerChampagnePercent * 360
            pathOuterChampagnePie.lineTo(0, 0)  # 画直线
            pathOuterChampagnePie.closeSubpath()  # 使该路径闭合
            pathOuterChampagnePie.addText(radius1 / 2 - 18, 5, painter.font(), "+X")
           
            # painter.restore()
            # 以下同理绘制小扇形
            radius = 50
            rect1 = QtCore.QRectF(-radius/2, -radius/2, radius, radius)
            pathMidPie = QtGui.QPainterPath()
            pathMidPie.arcMoveTo(rect1, -45)
            pathMidPie.arcTo(rect1, -45, 90)
            pathMidPie.lineTo(0, 0)
            pathMidPie.closeSubpath()
    
            # 大扇形减去小扇形,得到扇形饼圆
            self.rightBtnView = pathOuterChampagnePie.subtracted(pathMidPie)
            painter.setPen(Qt.NoPen)  # 边框线条无色
            painter.setBrush(Qt.gray)
            painter.drawPath(self.rightBtnView)
            #
            painter.restore()  # 恢复坐标系
    
        def drawOuterCircle(self, painter):
            """
                绘制顶部按钮
                 :param painter:
                 :return:
                 """
            painter.save()
            # 以下绘图保存至painter的坐标系统
            # 设置标志位,判断鼠标是否进入该区域。如果进入该区域,则半径扩大
            if self.mouseTopView:
                radius1 = self.outerPieRadius + 4
            else:
                radius1 = self.outerPieRadius
    
            # 绘制大扇形
    
            rect = QtCore.QRectF(-radius1 / 2, -radius1 / 2, radius1, radius1)  # 该扇形饼圆所在的region
            pathOuterChampagnePie = QtGui.QPainterPath()  # 新建QPainterPath对象
            pathOuterChampagnePie.arcMoveTo(rect, 45)  # 画弧线的起点角度,从0°开始
            pathOuterChampagnePie.arcTo(rect, 45, 90)  # 扇形饼圆弧度为self.outerChampagnePercent * 360
            pathOuterChampagnePie.lineTo(0, 0)  # 画直线
            pathOuterChampagnePie.closeSubpath()  # 使该路径闭合
            pathOuterChampagnePie.addText(-8, -radius1 / 2 + 15, painter.font(), "+Y")
     
            # painter.restore()
            # 以下同理绘制小扇形
            radius = 50
            rect1 = QtCore.QRectF(-radius / 2, -radius / 2, radius, radius)
            pathMidPie = QtGui.QPainterPath()
            pathMidPie.arcMoveTo(rect1, 45)
            pathMidPie.arcTo(rect1, 45, 90)
            pathMidPie.lineTo(0, 0)
            pathMidPie.closeSubpath()
    
            # 大扇形减去小扇形,得到扇形饼圆
            self.topBtnView = pathOuterChampagnePie.subtracted(pathMidPie)
            painter.setPen(Qt.NoPen)  # 边框线条无色
            painter.setBrush(Qt.yellow)
            painter.drawPath(self.topBtnView)
            #
            painter.restore()  # 恢复坐标系
    
        def drawInnerPie(self, painter):
            """
                 绘制左侧按钮
                 :param painter:
                 :return:
                 """
            painter.save()
            # 以下绘图保存至painter的坐标系统
            # 设置标志位,判断鼠标是否进入该区域。如果进入该区域,则半径扩大
            if self.mouseLeftView:
                radius1 = self.outerPieRadius + 4
            else:
                radius1 = self.outerPieRadius
    
            # 绘制大扇形
    
            rect = QtCore.QRectF(-radius1 / 2, -radius1 / 2, radius1, radius1)  # 该扇形饼圆所在的region
            pathOuterChampagnePie = QtGui.QPainterPath()  # 新建QPainterPath对象
            pathOuterChampagnePie.arcMoveTo(rect, 135)  # 画弧线的起点角度,从0°开始
            pathOuterChampagnePie.arcTo(rect, 135, 90)  # 扇形饼圆弧度为self.outerChampagnePercent * 360
            pathOuterChampagnePie.lineTo(0, 0)  # 画直线
            pathOuterChampagnePie.closeSubpath()  # 使该路径闭合
            pathOuterChampagnePie.addText(-radius1 / 2 + 5, 5, painter.font(), "-X")
          
            # 以下同理绘制小扇形
            radius = 50
            rect1 = QtCore.QRectF(-radius / 2, -radius / 2, radius, radius)
            pathMidPie = QtGui.QPainterPath()
            pathMidPie.arcMoveTo(rect1, 135)
            pathMidPie.arcTo(rect1, 135, 90)
            pathMidPie.lineTo(0, 0)
            pathMidPie.closeSubpath()
    
            # 大扇形减去小扇形,得到扇形饼圆
            self.leftBtnView = pathOuterChampagnePie.subtracted(pathMidPie)
            painter.setPen(Qt.NoPen)  # 边框线条无色
            painter.setBrush(Qt.darkGreen)  # 填充颜色
            painter.drawPath(self.leftBtnView)
            #
            painter.restore()  # 恢复坐标系
    
        def drawBottom(self, painter):
            """
                 绘制底部按钮
                 :param painter:
                 :return:
                 """
            painter.save()
            # 以下绘图保存至painter的坐标系统
            # 设置标志位,判断鼠标是否进入该区域。如果进入该区域,则半径扩大
            if self.mouseBottomView:
                radius1 = self.outerPieRadius + 4
            else:
                radius1 = self.outerPieRadius
    
            # 绘制大扇形
    
            rect = QtCore.QRectF(-radius1 / 2, -radius1 / 2, radius1, radius1)  # 该扇形饼圆所在的region
            pathOuterChampagnePie = QtGui.QPainterPath()  # 新建QPainterPath对象
            pathOuterChampagnePie.arcMoveTo(rect, 225)  # 画弧线的起点角度,从0°开始
            pathOuterChampagnePie.arcTo(rect, 225, 90)  # 扇形饼圆弧度为self.outerChampagnePercent * 360
            pathOuterChampagnePie.lineTo(0, 0)  # 画直线
            pathOuterChampagnePie.closeSubpath()  # 使该路径闭合
            pathOuterChampagnePie.addText(-8, radius1/2-5, painter.font(), "-Y")
    
            # 以下同理绘制小扇形
            radius = 50
            rect1 = QtCore.QRectF(-radius / 2, -radius / 2, radius, radius)
            pathMidPie = QtGui.QPainterPath()
            pathMidPie.arcMoveTo(rect1, 225)
            pathMidPie.arcTo(rect1, 225, 90)
            pathMidPie.lineTo(0, 0)
            pathMidPie.closeSubpath()
    
            # 大扇形减去小扇形,得到扇形饼圆
            self.bottomBtnView = pathOuterChampagnePie.subtracted(pathMidPie)
            painter.setPen(Qt.NoPen)  # 边框线条无色
            painter.setBrush(Qt.blue)
            painter.drawPath(self.bottomBtnView)
            #
            painter.restore()  # 恢复坐标系
    
        def drawMidCircle(self, painter):
            """
            中间按钮
            :param painter:
            :return:
            """
            if self.mouseCenterView:
                radius = 40 + 4
            else:
                radius = 40
            painter.save()
            painter.setPen(Qt.NoPen)
            painter.setBrush(Qt.red)
            path = QtGui.QPainterPath()
            path.addEllipse(-radius/2, -radius/2, radius, radius)
            path.addText(-10, 5, painter.font(), "home")
            painter.drawPath(path)
            self.centerBtnView = path
            # painter.drawEllipse(-radius/2, -radius/2, radius, radius)
            painter.restore()
            font = QFont()
    
        def paintEvent(self, event):
            # 绘制准备工作, 启用反锯齿
            painter = QtGui.QPainter(self)
            painter.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing)
    
            # 平移坐标中心,等比例缩放
            width = self.width()
            height = self.height()
            side = min(width, height)
            painter.translate(width / 2, height / 2)  # 坐标中心移至窗口中心位置
            painter.scale(side / 200.0, side / 200.0)  # 坐标刻度缩放为原来的(side/200)倍
    
            # 画圆
            self.drawOuterCircle(painter)  # 绘制顶部按钮
            self.drawMidCircle(painter)  # 绘制中间按钮
            self.drawOuterPie(painter)  # 绘制右侧按钮
            self.drawInnerPie(painter)  # 绘制左侧按钮
            self.drawBottom(painter)  # 绘制底部按钮
            # self.drawLegend(painter)  # 绘制图例
            # self.drawTitle(painter)  # 绘制左上角文字
    
        def mouseMoveEvent(self, event):
            print('鼠标移动')
            print(event.pos)
            # 坐标系转换,和之前painter转换坐标系相对应
            width = self.width()
            height = self.height()
            side = min(width, height)
            enterPoint = QtCore.QPoint((event.pos().x() - width / 2) / side * 200.0,
                                       (event.pos().y() - height / 2) / side * 200.0)
    
            # 判断鼠标是否进入,并置标志位
            if self.centerBtnView.contains(enterPoint):
                self.mouseCenterView = True
            else:
                self.mouseCenterView = False
    
            if self.bottomBtnView.contains(enterPoint):
                self.mouseBottomView = True
            else:
                self.mouseBottomView = False
    
            if self.rightBtnView.contains(enterPoint):
                self.mouseRightView = True
            else:
                self.mouseRightView = False
    
            if self.topBtnView.contains(enterPoint):
                self.mouseTopView = True
            else:
                self.mouseTopView = False
    
            if self.leftBtnView.contains(enterPoint):
                self.mouseLeftView = True
            else:
                self.mouseLeftView = False
    
            self.update()  # 重绘
    
        def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None:
            width = self.width()
            height = self.height()
            side = min(width, height)
            enterPoint = QtCore.QPoint((a0.pos().x() - width / 2) / side * 200.0,
                                       (a0.pos().y() - height / 2) / side * 200.0)
            # 判断鼠标是否进入,并置标志位
            if self.centerBtnView.contains(enterPoint):
                print("centerBtnView")
    
            if self.bottomBtnView.contains(enterPoint):
                print("bottomBtnView")
    
            if self.rightBtnView.contains(enterPoint):
                print('rightBtnView')
    
            if self.topBtnView.contains(enterPoint):
                print('topBtnView')
    
            if self.leftBtnView.contains(enterPoint):
                print('leftBtnView')
    

    相关文章

      网友评论

        本文标题:PyQt5 异形按钮

        本文链接:https://www.haomeiwen.com/subject/frdxfdtx.html