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')