You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySide6如何等待动画播放完成后再切换QStackedWidget页面

PySide6 中 QStackedWidget 切换时淡出动画失效修复方案

问题原因

setCurrentIndex调用后会在当前事件循环周期内立即完成页面隐藏与切换,不会等待200ms的淡出动画播放完成,因此直接调用时动画还没来得及渲染就已经切到下一页。

  • time.sleep方案不可行:Qt所有UI绘制、动画帧更新都依赖主线程事件循环,sleep会直接阻塞事件循环,导致界面卡死、动画帧无法刷新
  • 子线程执行切换方案不可行:Qt所有UI控件操作都必须在主线程执行,跨线程操作UI属于未定义行为,轻则逻辑失效重则程序崩溃

正确实现逻辑

核心思路是等淡出动画完全播放结束后,再触发页面切换操作,通过动画的finished信号回调执行切换逻辑,完全不阻塞主线程。
另外需要注意:QGraphicsOpacityEffect、QPropertyAnimation、QParallelAnimationGroup对象不能写成函数内的局部变量,否则会被Python垃圾回收机制提前回收,导致动画异常中断。

修正后可直接复用的代码

def transition_to_target_page(self, target_page_index: int):
    # 初始化当前页控件的透明度效果,绑定为实例属性避免被垃圾回收
    self.title_opacity_effect = QGraphicsOpacityEffect(self.title)
    self.btn_opacity_effect = QGraphicsOpacityEffect(self.reminder_btn)
    self.title.setGraphicsEffect(self.title_opacity_effect)
    self.reminder_btn.setGraphicsEffect(self.btn_opacity_effect)

    # 初始化两个控件的淡出动画
    self.title_fade_out = QPropertyAnimation(self.title_opacity_effect, b"opacity")
    self.btn_fade_out = QPropertyAnimation(self.btn_opacity_effect, b"opacity")

    # 统一配置动画参数,从完全不透明淡出到全透明,时长200ms
    for anim in [self.title_fade_out, self.btn_fade_out]:
        anim.setStartValue(1)
        anim.setEndValue(0)
        anim.setDuration(200)

    # 配置并行动画组
    self.fade_out_anim_group = QParallelAnimationGroup()
    self.fade_out_anim_group.addAnimation(self.title_fade_out)
    self.fade_out_anim_group.addAnimation(self.btn_fade_out)

    # 绑定动画完成回调:淡出结束后再执行页面切换
    self.fade_out_anim_group.finished.connect(lambda: self._execute_page_switch(target_page_index))
    self.fade_out_anim_group.start()

def _execute_page_switch(self, target_index: int):
    # 执行实际的页面切换
    self.stacked_widget.setCurrentIndex(target_index)
    
    # 可选:给新页面增加淡入效果,过渡更自然
    new_page = self.stacked_widget.currentWidget()
    self.page_fade_in_effect = QGraphicsOpacityEffect(new_page)
    new_page.setGraphicsEffect(self.page_fade_in_effect)
    self.page_fade_in_anim = QPropertyAnimation(self.page_fade_in_effect, b"opacity")
    self.page_fade_in_anim.setStartValue(0)
    self.page_fade_in_anim.setEndValue(1)
    self.page_fade_in_anim.setDuration(200)
    self.page_fade_in_anim.start()

额外注意事项

  • 触发页面切换时,不要直接调用setCurrentIndex,而是调用transition_to_target_page(目标页索引)走带动画的切换流程
  • 如果需要实现整页的淡出淡入,不需要给页内每个控件单独加透明度效果,直接给整个页面widget加QGraphicsOpacityEffect做动画即可,代码更简洁
  • 如果需要实现滑动、缩放等更复杂的过渡效果,可以基于同样的信号回调逻辑扩展,不要在动画播放过程中直接执行页面切换操作

内容的提问来源于stack exchange,提问作者Omar Yacop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 19:31:11