I have two QVariantAnimation stuffed into a QSequentialAnimationGroup and I'm trying to invert one of them. I tried to do it like this
self.animation_1 = QtCore.QVariantAnimation()
self.animation_2 = QtCore.QVariantAnimation()
self.animation_1.setDirection(QtCore.QVariantAnimation.Backward)
self.animation_2.setDirection(QtCore.QVariantAnimation.Forward)
self.group = QtCore.QSequentialAnimationGroup(self)
self.group.addAnimation(self.animation_1)
self.group.addAnimation(self.animation_2)
But it didn’t work. I tried so
self.group.setDirection(QtCore.QVariantAnimation.Backward)
But the whole animation is inverted. and I only need to invert one of them. I tried to do this by referring to the index
self.group.animationAt(0).setDirection(QtCore.QVariantAnimation.Backward)
Zero reactions. I also tried to do it like this
self.group.animationAt(self.group.indexOfAnimation(animation_1)).setDirection(QtCore.QVariantAnimation.Backward)
It still didn't help.
How to do it?
My code
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Main(QtWidgets.QWidget):
def __init__(self):
super().__init__()
block = QtWidgets.QWidget(self)
block.setObjectName(u"block")
block.setMinimumSize(QtCore.QSize(300, 300))
self.block_but = QtWidgets.QWidget(block)
self.block_but.setObjectName(u"block_but")
self.block_but.setGeometry(QtCore.QRect(110, 20, 111, 111))
move_blur_button_lay = QtWidgets.QVBoxLayout(self.block_but)
move_blur_button_lay.setObjectName(u"move_blur_button_lay")
self.menu_arr = []
radio = QtWidgets.QPushButton(self.block_but)
radio.setText('click me')
radio.setObjectName("mv_radio_but")
radio.pressed.connect(self.menu_animation)
move_blur_button_lay.addWidget(radio)
for x in range(2):
menu = QtWidgets.QWidget(block)
menu.resize(50, 60)
menu._expand = False
self.menu_arr.append(menu)
self.menu_arr[0].setStyleSheet("""background:#ff0""")
self.animation = []
for i in range(2):
menuAnimation = QtCore.QVariantAnimation()
menuAnimation.setDuration(500)
menuAnimation.setEasingCurve(QtCore.QEasingCurve.OutQuart)
menuAnimation.setStartValue(QtCore.QPoint(-20, 10))
menuAnimation.setEndValue(QtCore.QPoint(0, 10))
self.animation.append(menuAnimation)
self.group = QtCore.QSequentialAnimationGroup(self)
def menu_animation(self):
for c in range(2):
pos1 = QtCore.QPoint(0, 0)
pos2 = QtCore.QPoint(100, 0)
self.animation[c].setStartValue(pos1)
self.animation[c].setEndValue(pos2)
self.animation[c].setDirection(QtCore.QAbstractAnimation.Backward)
self.animation[c].valueChanged.connect(
lambda value, val=c: self.fun(value, val)
)
#self.animation[0].setDirection(QtCore.QVariantAnimation.Backward)
#self.animation[1].setDirection(QtCore.QVariantAnimation.Forward)
self.animation[0].setStartValue(pos1)
self.animation[0].setEndValue(pos2)
self.animation[1].setStartValue(pos2)
self.animation[1].setEndValue(pos1)
self.group.addAnimation(self.animation[0])
self.group.addAnimation(self.animation[1])
self.group.start()
def fun(self, value, val=""):
self.menu_arr[val].move(value.x(), 0)
StyleSheet = """
QWidget QWidget,
QWidget QWidget QWidget QWidget,
QWidget QWidget QWidget QWidget QWidget QWidget,
QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget,
QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget{
background:#000;
color:#fff;
}
QWidget,
QWidget QWidget QWidget,
QWidget QWidget QWidget QWidget QWidget,
QWidget QWidget QWidget QWidget QWidget QWidget QWidget,
QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget{
background:#fff;
color:#000;
}
"""
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setStyleSheet(StyleSheet)
w = Main()
w.resize(640, 570)
w.show()
sys.exit(app.exec_())
What I want to get
It seems that it is not documented how the direction of QSequentialAnimationGroup affects the directions of the animations, but if the source code is reviewed:
void QSequentialAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
{
Q_D(QSequentialAnimationGroup);
// we need to update the direction of the current animation
if (state() != Stopped && d->currentAnimation)
d->currentAnimation->setDirection(direction);
}
It is noted that the address of the QSequentialAnimationGroup is applied to the animations. The solution would be to override that method and override that behavior but unfortunately that method cannot be accessed from python.
A workaround would be to implement the logic by connecting the clicked
signal to the start()
method of the first animation and the finished
signal of the first animation to the start()
method of the second animation.
class Main(QtWidgets.QWidget):
def __init__(self):
super().__init__()
block = QtWidgets.QWidget(self)
block.setMinimumSize(300, 300)
self.block_but = QtWidgets.QWidget(block)
self.block_but.setGeometry(QtCore.QRect(110, 20, 111, 111))
radio = QtWidgets.QPushButton("click me", self.block_but)
move_blur_button_lay = QtWidgets.QVBoxLayout(self.block_but)
move_blur_button_lay.addWidget(radio)
first_widget = QtWidgets.QWidget(block)
first_widget.resize(50, 60)
first_widget.setStyleSheet("""background:#ff0""")
second_widget = QtWidgets.QWidget(block)
second_widget.resize(50, 60)
pos1 = QtCore.QPoint(0, 0)
pos2 = QtCore.QPoint(100, 0)
self.first_animation = QtCore.QVariantAnimation(
self,
duration=500,
easingCurve=QtCore.QEasingCurve.OutQuart,
startValue=pos1,
endValue=pos2,
direction=QtCore.QVariantAnimation.Forward,
valueChanged=first_widget.move,
)
self.second_animation = QtCore.QVariantAnimation(
self,
duration=500,
easingCurve=QtCore.QEasingCurve.OutQuart,
startValue=pos1,
endValue=pos2,
direction=QtCore.QVariantAnimation.Backward,
valueChanged=second_widget.move,
)
radio.clicked.connect(self.first_animation.start)
self.first_animation.finished.connect(self.second_animation.start)