--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eric6/E5Gui/E5AnimatedLabel.py Thu Apr 09 18:00:40 2020 +0200 @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a label widget showing an animated pixmap. +""" + +from PyQt5.QtCore import pyqtSlot, QTimer +from PyQt5.QtGui import QPixmap +from PyQt5.QtWidgets import QLabel + +import UI.PixmapCache + + +class E5AnimatedLabel(QLabel): + """ + Class implementing a label widget showing an animated pixmap. + """ + def __init__(self, parent=None, *, animationFile="", interval=100): + """ + Constructor + + @param parent reference to the parent window + @type QWidget + @keyparam animationFile path to the file containing the animation data + @type str + @keyparam interval interval in milliseconds between animation frames + @type int + """ + super(E5AnimatedLabel, self).__init__(parent) + + self.__timer = QTimer(self) + self.__timer.setInterval(interval) + self.__timer.timeout.connect(self.__animate) + + self.__currentFrame = 0 + self.__frames = 0 + self.__pixmap = None + self.__pixmapHeight = 0 + self.__animationFile = "" + self.__animationFileLoaded = False + + self.__loadAnimationFile(animationFile) + + def __loadAnimationFile(self, animationFile): + """ + Private method to load an animation file. + + @param animationFile path to the file containing the animation data + @type str + """ + self.__animationFile = animationFile + + pixmap = UI.PixmapCache.getPixmap(animationFile) + if not pixmap.isNull(): + self.__pixmap = pixmap + self.__pixmapHeight = pixmap.height() + self.__frames = pixmap.width() // pixmap.height() + # assume quadratic animation frames + self.__animationFileLoaded = True + else: + self.__pixmap = QPixmap() + self.__pixmapHeight = 0 + self.__frames = 0 + self.__animationFileLoaded = False + + self.reset() + + @pyqtSlot() + def __animate(self): + """ + Private slot to animate the pixmap. + """ + if self.__animationFileLoaded: + self.__currentFrame = (self.__currentFrame + 1) % self.__frames + super(E5AnimatedLabel, self).setPixmap(self.__pixmap.copy( + self.__currentFrame * self.__pixmapHeight, + 0, + self.__pixmapHeight, + self.__pixmapHeight + )) + else: + self.clear() + + @pyqtSlot() + def reset(self): + """ + Public slot to reset the animation. + """ + self.__currentFrame = -1 + self.__animate() + + @pyqtSlot() + def start(self): + """ + Public slot to start the animation. + """ + if self.__animationFileLoaded: + self.__timer.start() + + @pyqtSlot() + def stop(self): + """ + Public slot to stop the animation. + """ + self.__timer.stop() + + def isActive(self): + """ + Public method to check, if the animation is active. + + @return flag indicating an active animation + @rtype bool + """ + return self.__timer.isActive() and self.__animationFileLoaded + + def setAnimationFile(self, animationFile): + """ + Public method to set the name of the animation file. + + @param animationFile path to the file containing the animation data + @type str + """ + active = self.__timer.isActive() + self.__timer.stop() + self.__loadAnimationFile(animationFile) + if active and self.__animationFileLoaded: + self.__timer.start() + + def getAnimationFile(self): + """ + Public method to get the name of the animation file. + + @return path to the file containing the animation data + @rtype str + """ + return self.__animationFile + + def isAnimationFileLoaded(self): + """ + Public method to check, if the animation file was loaded. + + @return flag indicating a successfully loaded animation file + @rtype bool + """ + return self.__animationFileLoaded + + def setInterval(self, interval): + """ + Public method to set the interval between the animated frames. + + @param interval interval in milliseconds between animation frames + @type int + """ + self.__timer.setInterval(interval) + + def getInterval(self): + """ + Public method to get the interval between the animated frames. + + @return interval in milliseconds between animation frames + @rtype int + """ + return self.__timer.interval() + + def setPixmap(self, pixmap): + """ + Public slot to set the pixmap of the label. + + Setting a standard pixmap will stop the animation and set the given + pixmap without animating it. Thereafter the animation has to be + restarted with the start() method. + + @param pixmap pixmap to be set + @type QPixmap + """ + self.stop() + super(E5AnimatedLabel, self).setPixmap(pixmap)