开发者

PyQt通过动画实现平滑滚动的QScrollArea

开发者 https://www.devze.com 2023-01-29 09:18 出处:网络 作者: 之一Yo
目录前言实现过程SmoothScrollBarSmoothScrollArea测试前言 在之前的博客《如何在 pyqt 中实现平滑滚动的 QScrollArea》中,我们使用定时器和队列实现了平滑滚动。但是实现代码还是有一点复杂,所以这篇博客将使用 Q
目录
  • 前言
  • 实现过程
    • SmoothScrollBar
    • SmoothScrollArea
  • 测试

    前言

    在之前的博客《如何在 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 mouseRele编程aseEvent(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()qTSUG.__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):
            android""" 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.setScrollAnim开发者_JAVAation(Qt.Vertical, 400, QEasingCurve.OutQuint)
            self.setScrollAnimation(Qt.Horizontal, 400, QEasingCurve.OutQuint)
    
            self.horizontalScrollBar().setValue(1900)
            self.setWidget(self.label)
       python     self.resize(1200, 800)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        w = Demo()
        w.show()
        app.exec_()
    

    最后

    至此平滑滚动的实现方式就已介绍完毕了,更多自定义小部件可以参见 PyQt-Fluent-Widgets

    到此这篇关于PyQt通过动画实现平滑滚动的QScrollArea的文章就介绍到这了,更多相关PyQt QScrollArea内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号