import sys
import math
from PyQt5.QtCore import Qt, QPropertyAnimation, QParallelAnimationGroup, QPointF, QEasingCurve, QSize
from PyQt5.QtGui import QGuiApplication, QPixmap, QIcon
from PyQt5.QtWidgets import QMainWindow, QApplication, QGraphicsView, QGraphicsScene, QPushButton
from mainWin import Ui_MainWindow
# 自定义GraphicsView的子类,并实现按钮的添加
class MyGraphics(QGraphicsView):
def __init__(self, parent=None):
super(MyGraphics, self).__init__(parent)
self.__initView()
self.resize(166, 156)
def __initView(self):
self.scene = QGraphicsScene()
self.scene.setSceneRect(0, 0, 150, 150)
self.ref_x0 = self.scene.width() / 2 # 场景的中心x坐标
self.ref_y0 = self.scene.height() / 2 # 场景的中新y坐标
self.btnProxyList = []
btn1 = QPushButton(QIcon(QPixmap("openConfigFolder.png")), None)
btn2 = QPushButton(QIcon(QPixmap("newFile.png")), None)
btn2.setToolTip('New case file')
btn_size = 40
btn1.resize(btn_size, btn_size)
btn2.resize(btn_size, btn_size)
btn1_proxy = self.scene.addWidget(btn1)
btn1_proxy.setPos(self.ref_x0 - btn1_proxy.rect().width()/2, self.ref_y0 - btn1_proxy.rect().height()/2)
self.btnProxyList.append(btn1_proxy)
btn2_proxy = self.scene.addWidget(btn2)
btn2_proxy.setPos(self.ref_x0 - btn2_proxy.rect().width()/2, self.ref_y0 - btn2_proxy.rect().height()/2)
self.btnProxyList.append(btn2_proxy)
btn3 = QPushButton(QIcon("uploadWeight.png"), None)
btn4 = QPushButton(QIcon("coffee.png"), None)
btn3.resize(btn_size, btn_size)
btn4.resize(btn_size, btn_size)
btn3_proxy = self.scene.addWidget(btn3)
btn3_proxy.setPos(self.ref_x0 - btn3_proxy.rect().width() / 2, self.ref_y0 - btn3_proxy.rect().height() / 2)
self.btnProxyList.append(btn3_proxy)
btn4_proxy = self.scene.addWidget(btn4)
btn4_proxy.setPos(self.ref_x0 - btn4_proxy.rect().width() / 2, self.ref_y0 - btn4_proxy.rect().height() / 2)
self.btnProxyList.append(btn4_proxy)
btn5 = QPushButton(QIcon("punch.png"), None)
btn6 = QPushButton(QIcon("role.png"), None)
btn5.resize(btn_size, btn_size)
btn6.resize(btn_size, btn_size)
btn5_proxy = self.scene.addWidget(btn5)
btn5_proxy.setPos(self.ref_x0 - btn5_proxy.rect().width() / 2, self.ref_y0 - btn5_proxy.rect().height() / 2)
self.btnProxyList.append(btn5_proxy)
btn6_proxy = self.scene.addWidget(btn6)
btn6_proxy.setPos(self.ref_x0 - btn6_proxy.rect().width() / 2, self.ref_y0 - btn6_proxy.rect().height() / 2)
self.btnProxyList.append(btn6_proxy)
for x in range(6):
eval(f"btn{x+1}").setIconSize(QSize(30,30))
eval(f"btn{x+1}").setStyleSheet("background: #ffffff;border:2px solid #001721;border-radius: 20px;")
self.setScene(self.scene)
# 鼠标离开widget时执行的动作
def leaveEvent(self, event):
if self.isVisible():
self.hide()
pass
# 按钮动画,每次弹出时,都要调用一次
def btnAnimate(self):
R = 60 # 动画时,圆周的半径
item_number = len(self.items())
angle = [x*round(float(360/item_number), 2) for x in range(item_number)]
animateTime = 200 # 动画持续时间
self.group = QParallelAnimationGroup(self)
num = 0
for item in self.btnProxyList:
animation = QPropertyAnimation(item, b'pos')
animation.setStartValue(QPointF(self.ref_x0 - item.rect().width() / 2,
self.ref_y0 - item.rect().height() / 2))
animation.setEndValue(
QPointF(self.ref_x0 + R * math.cos(angle[num] * math.pi / 180) - item.rect().width() / 2,
self.ref_y0 - R * math.sin(angle[num] * math.pi / 180) - item.rect().height() / 2))
animation.setDuration(animateTime)
animation.setEasingCurve(QEasingCurve.InCubic)
self.group.addAnimation(animation)
num += 1
self.group.start()
self.update()
class MainWin(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWin, self).__init__()
self.setupUi(self)
self.resize(730, 500)
self.__initUI()
self.handle()
def __initUI(self):
self.label.setFixedHeight(30)
self.label.setFixedWidth(30)
pix = QPixmap("tool.png")
pix.scaled(self.label.size(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) # 让图片填充满QLabel
# pix.scaled(self.label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
self.label.setPixmap(pix)
self.label.setScaledContents(True)
self.pushButton.setStyleSheet("background: #ffffff;border:3px solid #FF0000;border-radius:50px;")
self.view = MyGraphics()
def handle(self):
self.label.enterSignal.connect(self.showPopMenu)
def showPopMenu(self, labelPos):
# print(self.view.style().pixelMetric(QStyle.PM_TitleBarHeight)) # 获取标题栏高度
self.view.setStyleSheet("background: transparent;border:0px")
self.view.setWindowFlags(Qt.FramelessWindowHint)
self.view.setAttribute(Qt.WA_TranslucentBackground)
self.view.move(int(labelPos[0] - self.view.width() / 2), int(labelPos[1] - self.view.height()/2))
self.view.show()
self.view.btnAnimate()
self.view.setMouseTracking(True)
if __name__ == '__main__':
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
app = QApplication(sys.argv)
main_win = MainWin()
main_win.show()
sys.exit(app.exec_())