#python #animation #pyqt #pyqt5
#python #Анимация #pyqt #pyqt5
Вопрос:
Я создал два фрейма и кнопку в своем приложении, я хочу анимировать изменение размера фреймов при нажатии этой кнопки. Я создал две функции * (которые должны работать одинаково) * для анимации кадров, * (см. Код ниже) *.
Если вы запустите код как есть, он анимирует фрейм так, как я хотел, но если вы используете вторую функцию * (которую я закомментировал) *, она не будет работать. Я не знаю, почему? Может кто-нибудь, пожалуйста, объясните это. Если возможно, решение.
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()
Проблема с моим текущим подходом * (который работает нормально) * заключается в том, что мне придется делать это для каждого элемента вручную, а в моем исходном коде это было бы громоздко из-за большого количества элементов,
Второй подход упростил бы задачу, но он не работает. Попробуйте код и, пожалуйста, укажите, что я делаю неправильно.
Сначала попробуйте, как есть. А затем с # self.btn.clicked.connect(self.anim_fctn_i_want) # This animation should be working
Ответ №1:
Проблема в том, что в этом случае область действия анимаций ограничена областью действия списка, а список — это переменная, которая будет немедленно удалена, а следовательно, и анимации, поэтому их эффект не будет виден. Решение состоит в том, чтобы продлить жизненный цикл анимации, и для этого есть несколько вариантов, таких как превращение списка в атрибут класса или передача родительского элемента анимации, поскольку они являются QObjects, в этом случае будет использоваться второй:
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
С другой стороны, если вы собираетесь обрабатывать несколько анимаций параллельно, то по соображениям производительности лучше использовать 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
Комментарии:
1. Я понял вашу точку зрения, спасибо. Я сделал список переменной класса, и он работал нормально. да, «область действия анимаций ограничена областью действия списка, а список — это переменная, которая будет удалена мгновенно, и, следовательно, также анимация» это была проблема. Спасибо, что указали.