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

窗口尺寸变化时,如何结合Paint Event适配Widget的动画路径

Fixing Path Animation Issues in PyQt5 Widget

Hey there! Let's work through those two problems you're facing with your path animation widget. I'll break down the fixes step by step:

Problem 1: Animation sticks to old path when window resizes

Your original code creates the path with fixed 400x400 coordinates and initializes the animation only once on double-click. Even though the path updates in paintEvent when the window resizes, the running animation never picks up this new path.

Problem 2: Widget doesn't adapt to window size changes

The painter.setWindow(0, 0, 400, 400) line locks the painter's coordinate system to a fixed size, so both the drawn path and the button's position won't scale with the window.


Modified Code with Complete Fixes

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

class PathAnimation(QPropertyAnimation):
    def __init__(self, path=QPainterPath(), object=None, property=None):
        super().__init__(object, property)
        self.path = path

    def updateCurrentTime(self, currentTime):
        easedProgress = self.easingCurve().valueForProgress(currentTime / self.duration())
        pt = self.path.pointAtPercent(easedProgress)
        self.updateCurrentValue(pt)
        self.valueChanged.emit(pt)

    # Add a method to update the animation's path dynamically
    def setPath(self, path):
        self.path = path

class DemoB(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(400, 400)
        self.button = QPushButton('test', self)
        self.ani = None
        # Initialize path with current window size
        self.updatePath()

    def updatePath(self):
        # Generate path using the widget's actual current dimensions
        self.path = QPainterPath()
        self.path.moveTo(0, 0)  # Start at top-left corner
        # Use widget width/height for curve control points
        self.path.cubicTo(
            QPointF(0, self.height()),
            QPointF(self.width() / 2, 0),
            QPointF(self.width(), self.height())
        )

    def resizeEvent(self, event):
        super().resizeEvent(event)
        # Refresh path whenever window is resized
        self.updatePath()
        # If animation is running, update its path immediately
        if self.ani and self.ani.state() == QAbstractAnimation.Running:
            self.ani.setPath(self.path)
        # Trigger repaint to show the updated path
        self.update()

    def mouseDoubleClickEvent(self, e):
        # Restart animation with the latest path
        if self.ani:
            self.ani.stop()
        self.ani = PathAnimation(self.path, self.button, b'pos')
        self.ani.setDuration(2000)
        self.ani.start()

    def paintEvent(self, e):
        painter = QPainter(self)
        # Remove fixed coordinate lock - use widget's native system
        painter.drawPath(self.path)

app = QApplication([])
demo = DemoB()
demo.show()
app.exec()

Key Changes Explained

  • Dynamic Path Generation: The new updatePath() method creates the cubic curve using the widget's current width() and height() instead of hardcoded values. This ensures the path always matches the window size.
  • Resize Event Handling: Overriding resizeEvent() lets us update the path the moment the window changes size. If the animation is running, we immediately update its path so the button follows the new curve.
  • Fixed Coordinate Lock Removed: By deleting painter.setWindow(0, 0, 400, 400), the painter uses the widget's actual coordinate system, making both the path and button position scale with the window.
  • Animation Management: We track the animation instance to either update its path mid-run or recreate it with the latest path when double-clicking again.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:24:25