I'm trying to create an animation to hide unselected rows in a QTableWidget. I want the height of the rows to decrease until it is 0, for a smoother transition.
I found the following in C++ that does exactly what I'm trying to achieve, but I cannot get the same result in Python: https://forum.qt.io/topic/101437/animate-qtablewidget/4
I noticed they use Q_PROPERTY, but I honestly do not understand how it works...
Here what I came up for now (the animation is not working): `
import sys
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2.QtCore import *
class Example(QWidget):
def __init__(self):
super().__init__()
self.resize(600,200)
self.initUI()
def initUI(self):
layout = QHBoxLayout()
self.table = QTableWidget()
self.table.setColumnCount(3)
tableLabels = ["First Name", "Surname", "Age"]
self.table.setHorizontalHeaderLabels(tableLabels)
self.table.setRowCount(3)
self.table.verticalHeader().setMinimumSectionSize(1)
users = {
'0': ["peter", "parker", "19"],
'1': ["bruce", "banner", "42"],
'2': ["barry", "allen", "35"]
}
for row, data in users.items():
for column, value in enumerate(data):
self.table.setItem(int(row), column, QTableWidgetItem(value))
button1 = QPushButton("Hide")
button1.clicked.connect(lambda: self.hide_row())
layout.addWidget(self.table)
layout.addWidget(button1)
self.setLayout(layout)
self.show()
def hide_row(self):
for i in [x for x in range(self.table.rowCount()) if x != self.table.currentRow()]:
self.rowHeight = QPropertyAnimation(self.table.item(i, 0), b"geometry")
self.rowHeight.setDuration(400)
self.rowHeight.setStartValue(QRect(0, 0, 0, self.table.rowHeight(i)))
self.rowHeight.setEndValue(QRect(0, 0, 0, 0))
self.rowHeight.start()
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
`
Any idea how to achieve this goal in Python?
A Qt animation requires that the parent (or target, in the case of a Property Animation) inherits from QObject, and table widget items do not.
Also, the geometry
property should exist for the target object, and items do not have such a property.
The solution is to use a QVariantAnimation and use the valueChanged signal to set the row height on the table.
class Example(QWidget):
def __init__(self):
super().__init__()
self.resize(600,200)
self.initUI()
self.animation = QVariantAnimation(self)
self.animation.setDuration(400)
self.animation.valueChanged.connect(self.animationChanged)
self.animation.finished.connect(self.finished)
def animationChanged(self, height):
self.table.setRowHeight(self.currentRow, height)
def finished(self):
self.table.setRowHidden(self.currentRow, True)
# reset the height, so that we can use it as a "stored" value in case
# we want to show the row again
self.table.setRowHeight(self.currentRow, self.currentHeight)
def hide_row(self):
# ignore if the animation is already resizing a row
if self.animation.state():
return
self.currentRow = self.table.currentRow()
self.currentHeight = self.table.rowHeight(self.currentRow)
self.animation.setStartValue(self.currentHeight)
self.animation.setEndValue(1)
self.animation.start()
# ...