【问题标题】:Working with 2D arrays with QPropertyAnimation in PyQt5 Python在 PyQt5 Python 中使用 QPropertyAnimation 处理二维数组
【发布时间】:2021-11-07 08:31:47
【问题描述】:

当我使用带有一维数组的 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 个,这是所有图像的最后一个动画!

【问题讨论】:

    标签: python pyqt5 qpropertyanimation


    【解决方案1】:

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

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

            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

    【讨论】:

    • 感谢您的回答!这是一个非常、清晰和有教益的。它完全按照我想要的方式解决了我的问题。我开始用 C 语言编码,所以这就是为什么我不必要地使用额外的列表和其他东西:) 我想我必须以某种方式习惯 python 功能。
    • @FatihTüz 不客气。 C/C++ 需要更明确的语法,但请记住,即使在那里您也不需要明确的“计数”:始终可以获取“数组”的大小,并且您应该在任何 for 循环构造函数中使用它。也就是说,请记住,虽然 python 列表的行为几乎与数组一样,但它们并不相同:最重要的是,数组要求所有元素的类型相同,而 python 列表可以包含 any 类型。您还需要在使用之前声明一个数组,而在 Python 中,您可以“即时”创建列表(考虑列表推导)。
    猜你喜欢
    • 1970-01-01
    • 2017-10-28
    • 2014-07-13
    • 2017-09-20
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多