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 from utils.image_paths import ImagePaths 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(ImagePaths.SYSTEM_CENTER_POPUP_BG) 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("系统设置", ImagePaths.SYSTEM_SETTING_BG1, ImagePaths.SYSTEM_SETTING_BG2) self.data_btn = CustomButton("数据中心", ImagePaths.SYSTEM_DATA_CENTER_BG1, ImagePaths.SYSTEM_DATA_CENTER_BG2) self.user_btn = CustomButton("用户中心", ImagePaths.SYSTEM_USER_CENTER_BG1, ImagePaths.SYSTEM_USER_CENTER_BG2) # 按钮点击 → 发射对应信号(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())