lolveley
lolveley

Reputation: 1709

QVariantAnimation of opacity : the item appears at the end of the animation

here is an example where the graphicsitem appears at the end of the animation, and not progressively, as it should.

import sys

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import Qt, QEasingCurve
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QMainWindow, QGraphicsScene, QGraphicsView, QGraphicsPixmapItem, QGraphicsItem


class QStone(QGraphicsPixmapItem):
    def __init__(self):
        QGraphicsPixmapItem.__init__(self)

        white = QPixmap("white2.png")
        self.setPixmap(white.scaled(60, 60, Qt.KeepAspectRatio))
        self.w = self.boundingRect().width()
        self.h = self.boundingRect().height()


class QBoard(QGraphicsView):
    def __init__(self,scene):
        QGraphicsView.__init__(self)
        self.scene=scene
        self.setScene(scene)

    def display_stone(self, x, y):
        stone = QStone()
        stone.setZValue(10)
        stone.setOpacity(0)
        stone.setPos(x - stone.w / 2, y - stone.h / 2)
        self.scene.addItem(stone)

        animation = QtCore.QVariantAnimation(self.scene)
        animation.setDuration(3000)
        animation.valueChanged.connect(stone.setOpacity)
        # animation.setStartValue(0)
        # animation.setEndValue(1)
        animation.setParent(self.scene)
        animation.setEasingCurve(QEasingCurve.BezierSpline)
        animation.start()


class MainWindow(QMainWindow):
    def __init__(self):

        #all the usual stuff
        QMainWindow.__init__(self)
        centralWidget = QtWidgets.QWidget(self)
        self.setCentralWidget(centralWidget)
        mainLayout = QtWidgets.QGridLayout()
        centralWidget.setLayout(mainLayout)
        self.scene = QGraphicsScene()
        self.view = QBoard(self.scene)
        mainLayout.addWidget(self.view,0,0)
        self.scene.setSceneRect(-200.0,-150.0,400.0,300.0)

        self.view.display_stone(0,0)

app = QtWidgets.QApplication(sys.argv)
main_win = MainWindow()
main_win.show()
sys.exit(app.exec_())

instead of white2.png, plz put any image file.

any idea why it works like this?

all is said, I could also use QPropertyAnimation but it is more work for maybe the same result.

Upvotes: 1

Views: 512

Answers (1)

eyllanesc
eyllanesc

Reputation: 243897

QVariantAnimation generates an animation using the type of data deducted by the value passed in startValue and endValue, in your case by not placing it that implies using integer, or placing 0 and 1 that is the same makes integer values be used in the interpolation. What integer values can be interpolated between 0 and 1? because only 0 and 1, for example for t = 0.5 * T, the opacity value should be 0.5 considering if it is linear but how to use integers then the rounding set it to 0, and it will only be visible when t = T. The solution is to pass it as startValue at 0.0 and endValue at 1.0.

animation = QtCore.QVariantAnimation(self.scene)
animation.setDuration(3000)
animation.valueChanged.connect(stone.setOpacity)
animation.setStartValue(0.0) # <---
animation.setEndValue(1.0)   # <---
animation.setParent(self.scene)
animation.setEasingCurve(QEasingCurve.BezierSpline)
animation.start()

Upvotes: 2

Related Questions