在 PyQt5 中使用 QPropertyAnimation 处理二维数组 Python
Working with 2D arrays with QPropertyAnimation in PyQt5 Python
当我使用带有一维数组的 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 个,这是所有图像的最后一个动画!
如果你想有9个动画,你必须创建9个动画。您只是使用 3 并不断更改它们的 start/end 值。
无需创建不必要的列表,只需为动画创建一个列表,然后将它们附加到每个项目。您也不需要为列表计数使用实例属性,您可以使用预定义的值列表和 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。
当我使用带有一维数组的 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 个,这是所有图像的最后一个动画!
如果你想有9个动画,你必须创建9个动画。您只是使用 3 并不断更改它们的 start/end 值。
无需创建不必要的列表,只需为动画创建一个列表,然后将它们附加到每个项目。您也不需要为列表计数使用实例属性,您可以使用预定义的值列表和 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。