PyQt通过动画实现平滑滚动的QScrollArea
作者:之一Yo
这篇文章主要为大家详细介绍了PyQt如何使用Qt的动画框架 QPropertyAnimation来实现平滑滚动的QScrollArea,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的可以学习一下
前言
在之前的博客《如何在 pyqt 中实现平滑滚动的 QScrollArea》中,我们使用定时器和队列实现了平滑滚动。但是实现代码还是有一点复杂,所以这篇博客将使用 Qt 的动画框架 QPropertyAnimation
来实现相同的功能。
实现过程
SmoothScrollBar
滚动过程其实就是改变 QScrollBar
的 value()
的过程,Qt 自带的 QScrollArea
之所以无法平滑滚动,就是因为滚动时在 QScrollBar
的两个 value()
之间进行跳变。如果我们能在两个滚动值之间进行插值,就能实现平滑滚动了,这里通过重写 setValue()
函数来启动滚动动画。
""" Smooth scroll bar """ scrollFinished = pyqtSignal() def __init__(self, parent=None): QScrollBar.__init__(self, parent) self.ani = QPropertyAnimation() self.ani.setTargetObject(self) self.ani.setPropertyName(b"value") self.ani.setEasingCurve(QEasingCurve.OutCubic) self.ani.setDuration(500) self.ani.finished.connect(self.scrollFinished) def setValue(self, value: int): if value == self.value(): return # stop running animation self.ani.stop() self.scrollFinished.emit() self.ani.setStartValue(self.value()) self.ani.setEndValue(value) self.ani.start() def scrollValue(self, value: int): """ scroll the specified distance """ value += self.value() self.scrollTo(value) def scrollTo(self, value: int): """ scroll to the specified position """ value = min(self.maximum(), max(self.minimum(), value)) self.setValue(value) def mousePressEvent(self, e): self.ani.stop() super().mousePressEvent(e) def mouseReleaseEvent(self, e): self.ani.stop() super().mouseReleaseEvent(e) def mouseMoveEvent(self, e): self.ani.stop() super().mouseMoveEvent(e)
SmoothScrollArea
最后需要将 QScrollArea
的默认滚动条替换为平滑滚动的 SmoothScrollBar
:
class SmoothScrollArea(QScrollArea): """ Smooth scroll area """ def __init__(self, parent=None): super().__init__(parent) self.hScrollBar = SmoothScrollBar() self.vScrollBar = SmoothScrollBar() self.hScrollBar.setOrientation(Qt.Horizontal) self.vScrollBar.setOrientation(Qt.Vertical) self.setVerticalScrollBar(self.vScrollBar) self.setHorizontalScrollBar(self.hScrollBar) def setScrollAnimation(self, orient, duration, easing=QEasingCurve.OutCubic): """ set scroll animation Parameters ---------- orient: Orient scroll orientation duration: int scroll duration easing: QEasingCurve animation type """ bar = self.hScrollBar if orient == Qt.Horizontal else self.vScrollBar bar.ani.setDuration(duration) bar.ani.setEasingCurve(easing) def wheelEvent(self, e): if e.modifiers() == Qt.NoModifier: self.vScrollBar.scrollValue(-e.angleDelta().y()) else: self.hScrollBar.scrollValue(-e.angleDelta().x())
测试
下面是一个简单的图片查看器测试程序:
import sys from PyQt5.QtCore import QEasingCurve, Qt from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import QApplication, QLabel class Demo(SmoothScrollArea): def __init__(self): super().__init__() self.label = QLabel(self) self.label.setPixmap(QPixmap("shoko.jpg")) # customize scroll animation self.setScrollAnimation(Qt.Vertical, 400, QEasingCurve.OutQuint) self.setScrollAnimation(Qt.Horizontal, 400, QEasingCurve.OutQuint) self.horizontalScrollBar().setValue(1900) self.setWidget(self.label) self.resize(1200, 800) if __name__ == '__main__': app = QApplication(sys.argv) w = Demo() w.show() app.exec_()
最后
至此平滑滚动的实现方式就已介绍完毕了,更多自定义小部件可以参见 PyQt-Fluent-Widgets
到此这篇关于PyQt通过动画实现平滑滚动的QScrollArea的文章就介绍到这了,更多相关PyQt QScrollArea内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!