Python 学习

PyQt5 异形按钮

2022-11-25  本文已影响0人  bianruifeng
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')
上一篇下一篇

猜你喜欢

热点阅读