窗口尺寸变化时,如何结合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 currentwidth()andheight()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
相关产品推荐
相关产品推荐

