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

