I'm trying to fade out an entire row of a GridLayout when a user clicks a button. So far I've been able to loop each of the widgets on the specific row which is working but I'm struggling with creating a parallel animation for them all...
idx = self.parent().findChild(QGridLayout).indexOf(self)
location = self.parent().findChild(QGridLayout).getItemPosition(idx)
row, col = location[:2]
self.parent_grid = self.parent().findChild(QGridLayout)
col_count = self.parent().findChild(QGridLayout).columnCount()
print(col_count)
self.effects = []
self.animations = []
anim_group = QParallelAnimationGroup()
for i in range(col_count-1):
effect = QGraphicsOpacityEffect(self)
self.effects.append(effect)
self.parent_grid.itemAtPosition(row,i).widget().setGraphicsEffect(effect)
new_anim = QPropertyAnimation(effect, b"opacity")
new_anim.setDuration(1000)
new_anim.setStartValue(1)
new_anim.setEndValue(0)
new_anim.finished.connect(lambda: self.hide_widget(col_count, row))
self.animations.append(new_anim)
anim_group.addAnimation(new_anim)
anim_group.start()
Since the count of widgets might be high, it's not a good idea to create an animation for each one of them.
Instead, you can use a "controller" that has its own unique animation, and updates the opacity of each widgets in its row.
While using a QPropertyAnimation can work, it would require adding a custom property for that, and it's not really needed for this purpose. Instead, use a basic QVariantAnimation and connect its valueChanged
to a function that updates the opacity of each graphics effect.
Here is a possible implementation:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class RowFadeController(QObject):
def __init__(self, parent, buttons):
super().__init__()
self.buttons = buttons
self.effects = []
for button in buttons:
effect = QGraphicsOpacityEffect(button, opacity=1.0)
button.setGraphicsEffect(effect)
self.effects.append(effect)
self.animation = QVariantAnimation(self)
self.animation.setStartValue(1.)
self.animation.setEndValue(0.)
self.animation.valueChanged.connect(self.setOpacity)
def toggle(self, hide):
self.animation.setDirection(
self.animation.Forward if hide else self.animation.Backward
)
self.animation.start()
def setOpacity(self, opacity):
for effect in self.effects:
effect.setOpacity(opacity)
class Window(QWidget):
def __init__(self):
super().__init__()
layout = QGridLayout(self)
self.fadeControllers = []
for row in range(10):
rowButtons = []
for col in range(10):
button = QPushButton(str(col + 1))
layout.addWidget(button, row, col)
rowButtons.append(button)
toggleButton = QPushButton('toggle', checkable=True)
layout.addWidget(toggleButton, row, layout.columnCount() - 1)
fadeController = RowFadeController(self, rowButtons)
self.fadeControllers.append(fadeController)
toggleButton.clicked.connect(fadeController.toggle)
app = QApplication([])
test = Window()
test.show()
app.exec()