首页 > 解决方案 > 在 PyQt5 Python 中使用 QPropertyAnimation 处理二维数组

问题描述

当我使用带有一维数组的 QPropertyAnimation 时,没有问题。它接受所有的动画命令。但是,我想清除我的代码,因为我会处理很多图像。所以我尝试将二维数组用于图像及其动画。

与一维数组相同的逻辑(不在代码中):

self.animG = []
for i in range(3):
  self.animG.append(QPropertyAnimation(self.welcome, b"geometry")) 
...
...
...  
for i in range(len(self.animG)):
  if i == 0:
    self.animG[i].setDuration(1000)
    self.animG[i].setStartValue(QRect(-1920, 0, 1920, 1080))
    self.animG[i].setEndValue(QRect(0, 0, 1920, 1080))
  elif i == 1:
    self.animG[i].setDuration(2000)
    self.animG[i].setStartValue(QRect(0, 0, 1920, 1080))
    self.animG[i].setEndValue(QRect(0, 0, 1920, 1080))
  else:
    self.animG[i].setDuration(1000)
    self.animG[i].setStartValue(QRect(0, 0, 1920, 1080))
    self.animG[i].setEndValue(QRect(1920, 0, 1920, 1080))
...
...
  for i in range(3):
    self.anim_group.addAnimation(self.animG[i]) 

上面的代码完美运行,但我不想为每张图片创建这些主题。所以我认为类似下面的内容(所有代码,但需要部分指出)

from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QFrame
from PyQt5.QtCore import QPropertyAnimation, QRect, QPoint
import sys, time


class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.title = "Image Slider with PyQt5"
        self.InitWindow()

    def InitWindow(self):
        self.setWindowTitle(self.title)
        
        screenx = QtWidgets.QDesktopWidget().screenGeometry()
        print(screenx.width(), screenx.height())
        
        self.welcome = QtWidgets.QLabel(self)
        self.pixmapW = QtGui.QPixmap('Raspberry/WELCOME.jpg')
        self.welcome.setPixmap(self.pixmapW)

        self.label = QtWidgets.QLabel(self)
        self.pixmap = QtGui.QPixmap('Raspberry/image.jpg')
        self.label.setPixmap(self.pixmap)
        
        self.label2 = QtWidgets.QLabel(self)
        self.pixmap2 = QtGui.QPixmap('Raspberry/image2.jpg')
        self.label2.setPixmap(self.pixmap2)
        
        self.label.setGeometry(0, -1080, self.pixmap.width(), self.pixmap.height())
        self.label2.setGeometry(0, -1080, self.pixmap2.width(), self.pixmap2.height())
        self.welcome.setGeometry(0, 0, self.pixmapW.width(), self.pixmapW.height())        


        self.button = QPushButton("Start", self)
        self.button.setGeometry(((screenx.width() - 120)//2), ((screenx.height() - 80)//2), 120, 80)
        # QPropertyAnimation decleration
        self.propAnim = []
        self.propAnim.append(QPropertyAnimation(self.welcome, b"geometry"))
        self.propAnim.append(QPropertyAnimation(self.label, b"geometry"))
        self.propAnim.append(QPropertyAnimation(self.label2, b"geometry"))
        
        # Defining 2D array for images, and to embed QPropertAnimations
        self.imageCount, self.animCount = 3, 3
        self.animations = [[0 for x in range(self.imageCount)] for y in range(self.animCount)]
        
        # Embed 3 same animations scene to all images
        for i in range(self.imageCount):
            for j in range(self.animCount):
                self.animations[i][j] = (self.propAnim[i])
        
        self.anim_group = QtCore.QSequentialAnimationGroup()

        self.button.clicked.connect(self.doAni)
        self.anim_group.finished.connect(self.doAni)
        
        self.showMaximized()
        
    def doAni(self):
        self.label.setGeometry(0, -1080, self.pixmap.width(), self.pixmap.height())
        self.label2.setGeometry(0, -1080, self.pixmap2.width(), self.pixmap2.height())
        self.welcome.setGeometry(0, -1080, self.pixmapW.width(), self.pixmapW.height())
        
        for i in range(self.imageCount):
            for j in range(self.animCount):
                if j == 0:
                    self.animations[i][j].setDuration(2000)
                    self.animations[i][j].setStartValue(QRect(-1920, 0, 1920, 1080))
                    self.animations[i][j].setEndValue(QRect(0, 0, 1920, 1080))
                elif j == 1:
                    self.animations[i][j].setDuration(2000)
                    self.animations[i][j].setStartValue(QRect(0, 0, 1920, 1080))
                    self.animations[i][j].setEndValue(QRect(0, 0, 1920, 1080))
                elif j == 2:
                    self.animations[i][j].setDuration(2000)
                    self.animations[i][j].setStartValue(QRect(0, 0, 1920, 1080))
                    self.animations[i][j].setEndValue(QRect(1920, 0, 1920, 1080))
                else:
                    pass
        
        # HERE IS THE PROBLEMATIC PART, IT ONLY AND ONLY ACCEPTS 3rd ANIMATIONS FOR ALL IMAGES
        # NORMALLY IT SHOULD MAKE 9 MOVEMENTS TO COMPLETE SCENE
        # HOWEVER IT MAKES ONLY 3 MOVEMENTS

        for i in range(self.imageCount):
            for j in range(self.animCount):
                self.anim_group.addAnimation(self.animations[i][j])
       
        self.anim_group.start()

if __name__ == '__main__':
    App = QApplication(sys.argv)
    window = Window()
    sys.exit(App.exec())

正如您在代码的最后注释部分看到的,它必须制作 9 个动画动作,但它只制作了 3 个动画,这是所有图像的最后一个动画!

标签: pythonpyqt5qpropertyanimation

解决方案


如果你想有 9 个动画,你必须创建 9 个动画。您只是使用 3 并不断更改它们的开始/结束值。

无需创建不必要的列表,只需为动画创建一个列表,并将它们附加到每个项目。您也不需要为列表计数使用实例属性,并且您可以使用预定义的值列表以及动画zip()值之间循环。

        self.animations = []
        for i, widget in enumerate((self.welcome, self.label, self.label2)):
            widgetAnimations = []
            for j in range(self.animCount):
                widgetAnimations.append(QPropertyAnimation(widget, b"geometry"))
            self.animations.append(widgetAnimations)

    # ...
    def doAni(self):
        values = (
            (QRect(-1920, 0, 1920, 1080), QRect(0, 0, 1920, 1080)), 
            (QRect(0, 0, 1920, 1080), QRect(0, 0, 1920, 1080)), 
            (QRect(0, 0, 1920, 1080), QRect(1920, 0, 1920, 1080)), 
        )

        for widgetAnimations in self.animations:
            for animation, (start, end) in zip(widgetAnimations, values):
                animation.setStartValue(start)
                animation.setEndValue(end)
                animation.setDuration(2000)
                self.anim_group.addAnimation(animation)

请记住,如果要添加“暂停”动画,则应使用QPauseAnimation


推荐阅读