为什么 setDuration 在 QSequentialAnimationGroup 中不起作用?
Why does setDuration not work inside QSequentialAnimationGroup?
我将两个 QVariantAnimation 塞进了一个 QSequentialAnimationGroup 中,我正试图反转其中一个。我试过这样做
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)
但是没有用。我试过了
self.group.setDirection(QtCore.QVariantAnimation.Backward)
但是整个动画是倒转的。我只需要反转其中之一。
我试图通过参考索引
来做到这一点
self.group.animationAt(0).setDirection(QtCore.QVariantAnimation.Backward)
零反应。我也试过这样做
self.group.animationAt(self.group.indexOfAnimation(animation_1)).setDirection(QtCore.QVariantAnimation.Backward)
还是没有用。
怎么做?
我的代码
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_())
我想得到什么
似乎没有记载QSequentialAnimationGroup的方向如何影响动画的方向,但是如果the source code复习一下:
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);
}
注意到QSequentialAnimationGroup的地址被应用于动画。解决方案是覆盖该方法并覆盖该行为,但不幸的是无法从 python.
访问该方法
一种解决方法是通过将 clicked
信号连接到第一个动画的 start()
方法并将第一个动画的 finished
信号连接到 start()
第二个动画的方法。
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)
我将两个 QVariantAnimation 塞进了一个 QSequentialAnimationGroup 中,我正试图反转其中一个。我试过这样做
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)
但是没有用。我试过了
self.group.setDirection(QtCore.QVariantAnimation.Backward)
但是整个动画是倒转的。我只需要反转其中之一。 我试图通过参考索引
来做到这一点self.group.animationAt(0).setDirection(QtCore.QVariantAnimation.Backward)
零反应。我也试过这样做
self.group.animationAt(self.group.indexOfAnimation(animation_1)).setDirection(QtCore.QVariantAnimation.Backward)
还是没有用。
怎么做?
我的代码
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_())
我想得到什么
似乎没有记载QSequentialAnimationGroup的方向如何影响动画的方向,但是如果the source code复习一下:
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);
}
注意到QSequentialAnimationGroup的地址被应用于动画。解决方案是覆盖该方法并覆盖该行为,但不幸的是无法从 python.
访问该方法一种解决方法是通过将 clicked
信号连接到第一个动画的 start()
方法并将第一个动画的 finished
信号连接到 start()
第二个动画的方法。
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)