PyQt通過(guò)動(dòng)畫實(shí)現(xiàn)平滑滾動(dòng)的QScrollArea
前言
在之前的博客《如何在 pyqt 中實(shí)現(xiàn)平滑滾動(dòng)的 QScrollArea》中,我們使用定時(shí)器和隊(duì)列實(shí)現(xiàn)了平滑滾動(dòng)。但是實(shí)現(xiàn)代碼還是有一點(diǎn)復(fù)雜,所以這篇博客將使用 Qt 的動(dòng)畫框架 QPropertyAnimation
來(lái)實(shí)現(xiàn)相同的功能。
實(shí)現(xiàn)過(guò)程
SmoothScrollBar
滾動(dòng)過(guò)程其實(shí)就是改變 QScrollBar
的 value()
的過(guò)程,Qt 自帶的 QScrollArea
之所以無(wú)法平滑滾動(dòng),就是因?yàn)闈L動(dòng)時(shí)在 QScrollBar
的兩個(gè) value()
之間進(jìn)行跳變。如果我們能在兩個(gè)滾動(dòng)值之間進(jìn)行插值,就能實(shí)現(xiàn)平滑滾動(dòng)了,這里通過(guò)重寫 setValue()
函數(shù)來(lái)啟動(dòng)滾動(dòng)動(dòng)畫。
""" 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
的默認(rèn)滾動(dòng)條替換為平滑滾動(dòng)的 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())
測(cè)試
下面是一個(gè)簡(jiǎn)單的圖片查看器測(cè)試程序:
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_()
最后
至此平滑滾動(dòng)的實(shí)現(xiàn)方式就已介紹完畢了,更多自定義小部件可以參見(jiàn) PyQt-Fluent-Widgets
到此這篇關(guān)于PyQt通過(guò)動(dòng)畫實(shí)現(xiàn)平滑滾動(dòng)的QScrollArea的文章就介紹到這了,更多相關(guān)PyQt QScrollArea內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
django authenticate用戶身份認(rèn)證的項(xiàng)目實(shí)踐
Django的contrib.auth模塊中的authenticate()函數(shù)用于對(duì)用戶的憑據(jù)進(jìn)行身份驗(yàn)證,本文就來(lái)介紹一下django authenticate用戶身份認(rèn)證的使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08Python使用FastAPI制作一個(gè)視頻流媒體平臺(tái)
在構(gòu)建視頻流媒體平臺(tái)時(shí),用戶認(rèn)證與視頻上傳是兩個(gè)至關(guān)重要的功能,FastAPI作為一個(gè)高效的Web框架,可以輕松處理這些需求,下面我們看看具體實(shí)現(xiàn)方法吧2025-04-04Flask的圖形化管理界面搭建框架Flask-Admin的使用教程
Flask-Admin是一個(gè)為Python的Flask框架服務(wù)的微型框架,可以像Django-Admin那樣為用戶生成Model層面的數(shù)據(jù)管理界面,接下來(lái)就一起來(lái)看一下Flask的圖形化管理界面搭建框架Flask-Admin的使用教程2016-06-06解決python和pycharm安裝gmpy2 出現(xiàn)ERROR的問(wèn)題
這篇文章主要介紹了python和pycharm安裝gmpy2 出現(xiàn)ERROR的解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08使用Python來(lái)開(kāi)發(fā)Markdown腳本擴(kuò)展的實(shí)例分享
這篇文章主要介紹了使用Python來(lái)開(kāi)發(fā)Markdown腳本擴(kuò)展的實(shí)例分享,文中的示例是用來(lái)簡(jiǎn)單地轉(zhuǎn)換文檔結(jié)構(gòu),主要為了體現(xiàn)一個(gè)思路,需要的朋友可以參考下2016-03-03Python3字符串的常用操作方法之修改方法與大小寫字母轉(zhuǎn)化
這篇文章主要介紹了Python3字符串的常用操作方法之修改方法與大小寫字母轉(zhuǎn)化,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09Python繪制指數(shù)分布的概率密度函數(shù)圖
在數(shù)據(jù)科學(xué)和統(tǒng)計(jì)學(xué)中,指數(shù)分布是一種應(yīng)用廣泛的連續(xù)概率分布,通常用于建模獨(dú)立隨機(jī)事件發(fā)生的時(shí)間間隔,本文將展示如何在Python中繪制指數(shù)分布的概率密度函數(shù)圖,需要的可以了解下2024-12-12Python+Pygame實(shí)戰(zhàn)之炫舞小游戲的實(shí)現(xiàn)
提到QQ炫舞,可能很多人想到的第一個(gè)詞是“青春”?;腥婚g,這個(gè)承載了無(wú)數(shù)人回憶與時(shí)光的游戲品牌,已經(jīng)走到了第十幾個(gè)年頭。今天小編就來(lái)給大家嘗試做一款簡(jiǎn)單的簡(jiǎn)陋版的小游戲——《舞動(dòng)青春*炫舞》,感興趣的可以了解一下2022-12-12