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

PyQt中自定义Toggle开关按钮动画效果无法生效如何解决?

PyQt5 Toggle开关动画不生效问题修复方案

问题原因

  • 普通Python @property 装饰器声明的属性无法被Qt的元对象系统识别,QPropertyAnimation 只能操作通过Qt专属的@pyqtProperty装饰器声明的属性。
  • 动画初始化时参数调用错误,你误写了self.animation.setDirection(500),这个方法是用来设置动画播放方向的,正确的设置动画时长的方法是setDuration(500),参数单位为毫秒。

修复后的完整代码

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class ToggleButton(QCheckBox):
    def __init__(self, 
        width = 70, 
        bgColor = '#777', 
        circleColor = '#DDD', 
        activeColor = '#00BCff', 
        animationCurve = QEasingCurve.OutBounce
    ):
        QCheckBox.__init__(self)
        self.setFixedSize(width, 40)
        self.setCursor(Qt.PointingHandCursor)

        self._bg_color = bgColor
        self._circle_color = circleColor
        self._active_color = activeColor
        self._circle_position = 3
        self.animation = QPropertyAnimation(self, b"circle_position")
        self.animation.setEasingCurve(animationCurve)
        # 修复:设置动画时长为500毫秒
        self.animation.setDuration(500)
        self.stateChanged.connect(self.start_transition)

    # 修复:改用pyqtProperty声明属性
    @pyqtProperty(int)
    def circle_position(self):
        return self._circle_position

    @circle_position.setter
    def circle_position(self, pos):
        self._circle_position = pos
        self.update()

    def start_transition(self, value):
        print(self.isChecked())
        self.animation.stop()
        if value:
            self.animation.setEndValue(self.width() - 26)
        else:
            self.animation.setEndValue(3)

        self.animation.start()

    def hitButton(self, pos: QPoint):
        return self.contentsRect().contains(pos)


    def paintEvent(self, e):
        p = QPainter(self)
        p.setRenderHint(QPainter.Antialiasing)

        p.setPen(Qt.NoPen)

        rect = QRect(0, 0, self.width(), self.height())

        if not self.isChecked():
            p.setBrush(QColor(self._bg_color))
            p.drawRoundedRect(0, 0, rect.width(), self.height(), self.height() / 2, self.height() / 2)

            p.setBrush(QColor(self._circle_color))
            p.drawEllipse(self._circle_position, 3, 32, 32)
        
        else:
            p.setBrush(QColor(self._active_color))
            p.drawRoundedRect(0, 0, rect.width(), self.height(), self.height() / 2, self.height() / 2)

            p.setBrush(QColor(self._circle_color))
            p.drawEllipse(self._circle_position, 3, 32, 32)

        p.end()


class window(QMainWindow):
   def __init__(self, parent = None):
      super(window, self).__init__(parent)
      self.resize(500,500)
      self.setWindowTitle("PyQt5")
      self.toggleBtn = ToggleButton()
      self.container = QFrame()
      self.layout = QVBoxLayout()
      self.layout.addWidget(self.toggleBtn, Qt.AlignCenter, Qt.AlignCenter)
      self.container.setLayout(self.layout)
      self.setCentralWidget(self.container)


def main():
   app = QApplication(sys.argv)
   ex = window()
   ex.show()
   sys.exit(app.exec_())

if __name__ == '__main__':
   main()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 17:15:10