151 lines
6.3 KiB
Python
151 lines
6.3 KiB
Python
from PySide6.QtWidgets import (QApplication, QVBoxLayout, QPushButton, QDialog)
|
||
from PySide6.QtGui import QPixmap, QFont, QIcon, QPainter
|
||
from PySide6.QtCore import Qt, Signal
|
||
from PySide6.QtCore import Qt, Signal, QPropertyAnimation, QEasingCurve, QRect
|
||
import sys
|
||
|
||
import resources.resources_rc
|
||
|
||
class CustomButton(QPushButton):
|
||
def __init__(self, text, normal_icon, active_icon, parent=None):
|
||
super().__init__(text, parent)
|
||
self.normal_icon = normal_icon
|
||
self.active_icon = active_icon
|
||
self.setFixedSize(147, 36)
|
||
self.setCursor(Qt.PointingHandCursor)
|
||
self.update_icon(self.normal_icon)
|
||
self.setFont(QFont("", 17))
|
||
self.setStyleSheet("""
|
||
QPushButton {
|
||
color: #16ffff;
|
||
background: none;
|
||
outline: none;
|
||
border: none;
|
||
text-align: center;
|
||
background-color: transparent;
|
||
font-weight: Bold;
|
||
}
|
||
QPushButton:hover {
|
||
color: #001c83;
|
||
background-color: #16ffff;
|
||
background-repeat: no-repeat;
|
||
outline: none;
|
||
border: none;
|
||
}
|
||
""")
|
||
|
||
def update_icon(self, icon_path):
|
||
pixmap = QPixmap(icon_path)
|
||
if not pixmap.isNull():
|
||
scaled_pixmap = pixmap.scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||
self.setIcon(QIcon(scaled_pixmap))
|
||
self.setIconSize(scaled_pixmap.size())
|
||
else:
|
||
self.setIcon(QIcon())
|
||
|
||
def enterEvent(self, event):
|
||
self.update_icon(self.active_icon)
|
||
super().enterEvent(event)
|
||
|
||
def leaveEvent(self, event):
|
||
self.update_icon(self.normal_icon)
|
||
super().leaveEvent(event)
|
||
|
||
class SystemCenterDialog(QDialog):
|
||
# 定义三个信号,对应三个按钮的点击事件
|
||
sys_setting_clicked = Signal() # 系统设置点击信号
|
||
data_center_clicked = Signal() # 数据中心点击信号
|
||
user_center_clicked = Signal() # 用户中心点击信号
|
||
|
||
def __init__(self, parent=None):
|
||
super().__init__(parent)
|
||
self.init_ui()
|
||
self.init_animations() # 初始化动画
|
||
|
||
def init_ui(self):
|
||
# 弹窗基础设置
|
||
self.setWindowTitle("系统中心")
|
||
self.setWindowFlags(Qt.FramelessWindowHint) # 隐藏默认边框
|
||
self.setWindowOpacity(0.0) # 初始状态为完全透明,实现动画效果
|
||
|
||
# 加载背景图
|
||
self.background = QPixmap(":/icons/images/系统中心弹窗背景.png")
|
||
if self.background.isNull():
|
||
print("警告:系统中心弹窗背景.png 加载失败!")
|
||
self.setFixedSize(220, 200)
|
||
else:
|
||
self.setFixedSize(self.background.size())
|
||
|
||
# 主布局
|
||
main_layout = QVBoxLayout(self)
|
||
main_layout.setContentsMargins(0, 0, 0, 6)
|
||
main_layout.setSpacing(0)
|
||
main_layout.setAlignment(Qt.AlignCenter)
|
||
|
||
# 创建按钮并绑定信号发射
|
||
self.sys_btn = CustomButton("系统设置", ":/icons/images/系统设置背景1.png", ":/icons/images/系统设置背景2.png")
|
||
self.data_btn = CustomButton("数据中心", ":/icons/images/系统数据中心背景1.png", ":/icons/images/系统数据中心背景2.png")
|
||
self.user_btn = CustomButton("用户中心", ":/icons/images/系统用户中心背景1.png", ":/icons/images/系统用户中心背景2.png")
|
||
|
||
# 按钮点击 → 发射对应信号(dialog不处理业务逻辑,只传递事件)
|
||
self.sys_btn.clicked.connect(self.sys_setting_clicked.emit)
|
||
self.data_btn.clicked.connect(self.data_center_clicked.emit)
|
||
self.user_btn.clicked.connect(self.user_center_clicked.emit)
|
||
|
||
main_layout.addWidget(self.sys_btn)
|
||
main_layout.addWidget(self.data_btn)
|
||
main_layout.addWidget(self.user_btn)
|
||
|
||
def paintEvent(self, event):
|
||
painter = QPainter(self)
|
||
painter.drawPixmap(self.rect(), self.background)
|
||
super().paintEvent(event)
|
||
|
||
def init_animations(self):
|
||
"""初始化显示动画(可根据喜好选择或组合)"""
|
||
# 1. 淡入动画(透明度从0→1)
|
||
self.opacity_anim = QPropertyAnimation(self, b"windowOpacity")
|
||
self.opacity_anim.setDuration(300) # 动画时长300ms
|
||
self.opacity_anim.setStartValue(0.0)
|
||
self.opacity_anim.setEndValue(1.0)
|
||
self.opacity_anim.setEasingCurve(QEasingCurve.InOutCubic) # 缓动曲线(平滑加速减速)
|
||
|
||
# 2. 缩放动画(从80%→100%大小)
|
||
self.scale_anim = QPropertyAnimation(self, b"geometry")
|
||
self.scale_anim.setDuration(300)
|
||
# 起点和终点在显示时动态设置(依赖当前弹窗位置)
|
||
self.scale_anim.setEasingCurve(QEasingCurve.OutBack) # 带弹性的缓动曲线(弹出感)
|
||
|
||
# 3. 组合动画(同时执行淡入+缩放)
|
||
from PySide6.QtCore import QParallelAnimationGroup
|
||
self.anim_group = QParallelAnimationGroup(self)
|
||
self.anim_group.addAnimation(self.opacity_anim)
|
||
self.anim_group.addAnimation(self.scale_anim)
|
||
|
||
def showEvent(self, event):
|
||
"""重写显示事件,每次显示时启动动画"""
|
||
# 必须先调用父类showEvent,否则弹窗无法正常显示
|
||
super().showEvent(event)
|
||
|
||
# 动态设置缩放动画的起点(基于当前弹窗位置和大小)
|
||
current_geometry = self.geometry() # 弹窗当前位置和大小(已通过move设置)
|
||
# 起点:缩小到80%,并保持中心位置不变
|
||
start_rect = QRect(
|
||
current_geometry.center().x() - current_geometry.width() * 0.4,
|
||
current_geometry.center().y() - current_geometry.height() * 0.4,
|
||
int(current_geometry.width() * 0.8),
|
||
int(current_geometry.height() * 0.8)
|
||
)
|
||
self.scale_anim.setStartValue(start_rect)
|
||
self.scale_anim.setEndValue(current_geometry) # 终点:原始大小
|
||
|
||
# 启动组合动画
|
||
self.anim_group.start()
|
||
|
||
if __name__ == "__main__":
|
||
app = QApplication(sys.argv)
|
||
dialog = SystemCenterDialog()
|
||
# 测试信号(实际业务在控制器中绑定)
|
||
dialog.sys_setting_clicked.connect(lambda: print("系统设置被点击"))
|
||
dialog.show()
|
||
sys.exit(app.exec()) |