Issue
I've created two frames and a button in my app, I want to animate the resizing of frames when that button is pressed. I've created two functions * (which should work same)* for animating the frames, * (see the code below)*.
If you run the code as it is, It will animate the frame as I wanted, but if you use the second function * (which I've commented out)*, It will not work. I don't know why? Can somebody please explain this. If possible, a solution.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class Test(QMainWindow):
def __init__(self):
super().__init__()
self.resize(500, 500)
self.frame_to_animate()
# Creating items for the app
def frame_to_animate(self):
self.widget = QWidget()
self.setCentralWidget(self.widget)
# Frame to animate 1
self.frame = QFrame(self.widget)
self.frame.setStyleSheet('QFrame {background: red}')
self.frame.resize(100, 100)
# Frame to animate 2
self.frame2 = QFrame(self.widget)
self.frame2.move(0, 250)
self.frame2.setStyleSheet('QFrame {background: yellow}')
self.frame2.resize(100, 100)
self.thing = False
# Button to animate the frame
self.btn = QPushButton(self.widget)
self.btn.setText('Animate the frame')
self.btn.move(300, 200)
self.btn.clicked.connect(self.animation_fctn)
# self.btn.clicked.connect(self.anim_fctn_i_want) # This animation should be working
# I want this way to work, but it's not working
def anim_fctn_i_want(self):
anim_list = []
for item in [self.frame, self.frame2]:
anim_list.append(QPropertyAnimation(item, b"size"))
for anim in anim_list:
anim.setDuration(1000)
if self.thing is False:
anim.setEndValue(QSize(200, 200))
self.thing = True
else:
anim.setEndValue(QSize(100, 100))
self.thing = False
anim.start()
# Creating Animation one by one
def animation_fctn(self):
self.anim = QPropertyAnimation(self.frame, b"size")
self.anim2 = QPropertyAnimation(self.frame2, b"size")
self.anim.setDuration(1000)
self.anim2.setDuration(1000)
if self.thing is False:
self.anim.setEndValue(QSize(200, 200))
self.anim2.setEndValue(QSize(200, 200))
self.thing = True
else:
self.anim.setEndValue(QSize(100, 100))
self.anim2.setEndValue(QSize(100, 100))
self.thing = False
self.anim.start()
self.anim2.start()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Test()
window.show()
app.exec()
The problem with my current approach * (which is working fine)* is I'll have to do it for each item manually, and in my original code, it would be cumbersome because of many items,
Second approach would make it simple, but It's not working. Try the code and Please point out what I'm doing wrong.
First try as it is. And then with # self.btn.clicked.connect(self.anim_fctn_i_want) # This animation should be working
Solution
The problem is that in this case the scope of the animations is limited to the scope of the list, and the list is a variable that will be eliminated instantly, and therefore also the animations, so the effect of them will not be seen. The solution is to extend the life cycle of the animations and for this there are several options such as making the list an attribute of the class or passing a parent to the animations since they are QObjects, in this case the second will be used:
def anim_fctn_i_want(self):
for item in (self.frame, self.frame2):
anim = QPropertyAnimation(item, b"size", parent=item)
anim.setDuration(1000)
anim.setEndValue(QSize(100, 100) if self.thing else QSize(200, 200))
anim.start(QAbstractAnimation.DeleteWhenStopped)
self.thing = not self.thing
On the other hand, if you are going to handle several animations in parallel, then for performance reasons it is better to use the QParallelAnimationGroup:
def anim_fctn_i_want(self):
group_animation = QParallelAnimationGroup(self)
for item in (self.frame, self.frame2):
anim = QPropertyAnimation(item, b"size")
anim.setDuration(1000)
anim.setEndValue(QSize(100, 100) if self.thing else QSize(200, 200))
group_animation.addAnimation(anim)
group_animation.start(QAbstractAnimation.DeleteWhenStopped)
self.thing = not self.thing
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.