当前位置:主页 > python教程 > PyQt QScrollArea

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

发布:2023-03-12 15:00:01 59


给网友们整理相关的编程文章,网友赵幼怡根据主题投稿了本篇教程内容,涉及到PyQt动画实现平滑滚动QScrollArea、PyQt 平滑滚动QScrollArea、PyQt QScrollArea、PyQt QScrollArea相关内容,已被238网友关注,内容中涉及的知识点可以在下方直接下载获取。

PyQt 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内容请搜索码农之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持码农之家!


参考资料

相关文章

网友讨论