Adding an Animated Gif to a QLabel with Pyside

Time for another tutorial  not for the drag and drop (Got a bit distracted with the inspiration for this tutorial) but for adding an animated gif to a QLabel.

In this example I am loading the file into a QByteArray so we don't keep that GIF in memory. However you can add the GIF file directly to the QMovie as the first argument.

If you can't display the GIF in your own code, double check the qt.conf file and make sure that it is referring to the correct plugins folder. 

PS: If you don't recognise the GIF shown in the tool, you can find the Video here.("You are welcome"). 

import sys
import os
from PySide import QtCore, QtGui
ImagesFolder=os.path.join(os.path.dirname(__file__),'images')

class CucumberGifWidget(QtGui.QLabel):
    def __init__(self, parent=None):
        super(CucumberGifWidget, self).__init__(parent)
        self.setAcceptDrops(True)
        self.setFrameStyle(QtGui.QFrame.WinPanel | QtGui.QFrame.Sunken)
        self.setAlignment(QtCore.Qt.AlignCenter)
        self.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding)
        
        trashGif= open(os.path.join(ImagesFolder,'cucumber.gif'), 'rb').read()
        self.gifByteArray=QtCore.QByteArray(trashGif)
        self.gifBuffer=QtCore.QBuffer(self.gifByteArray)
        self.movie = QtGui.QMovie()
        self.movie.setFormat('GIF')
        self.movie.setDevice(self.gifBuffer)
        self.movie.setCacheMode(QtGui.QMovie.CacheAll)
        self.movie.setSpeed(100)
        self.setMovie(self.movie)
        self.movie.jumpToFrame(0)

    def dragEnterEvent(self, event):
        if event.mimeData().hasImage():
            event.setDropAction(QtCore.Qt.MoveAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        event.setDropAction(QtCore.Qt.MoveAction)
        if event.mimeData().hasImage():
            if "cucumber" in event.mimeData().text():
                self.movie.start()
                event.source().setParent(None)
                event.source().deleteLater()
            else:
                event.accept()
        else:
            event.ignore()

Drag and drop with Qt and PySide

I have always been using (well at least the past 7 years) QT for creating interfaces for my PySide/PyQt applications. Lately I've decided to dive a bit deeper to create and experiment with more complex behaviours. 

Starting with a convenient behaviour : Drag and Drop.

In the example I am sharing here I re-implemented the drag and drop related methods of a QLabel and a QWidget so we are able to drag the label into the widget. What actually happens is that when we drop the label on  the widget we create another Label with the same information,  it is a Copying action.

TODO: In the upcoming weeks we will add the functionality of re-arranging the labels in the Drop widget and also from one Drop widget to another.
import sys
from PySide import QtCore, QtGui

class InitialCard(QtGui.QLabel):
    def __init__(self, text, parent):
        super(InitialCard, self).__init__(text, parent)
        self.setAutoFillBackground(True)
        self.setFrameStyle(QtGui.QFrame.WinPanel|QtGui.QFrame.Sunken)
        newFont = QtGui.QFont("MsReferenceSansSerif", 10)
        newFont.setBold(False)
        self.setFont(newFont)
        self.setMinimumSize(90, 25)
        self.setMaximumHeight(30)
        self.setAlignment(QtCore.Qt.AlignCenter)
        self.mimeText=self.text()

    def mouseMoveEvent(self, event):
        if not self.text():
            return
        mimeData = QtCore.QMimeData()
        mimeData.setText(self.mimeText)
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)
        drag.exec_(QtCore.Qt.CopyAction | QtCore.Qt.MoveAction, QtCore.Qt.CopyAction)

class CardsDropWidget(QtGui.QWidget):

    def __init__(self, parent):
        super(CardsDropWidget, self).__init__(parent)
        self.setAcceptDrops(True)
        self.contentsVLO = QtGui.QVBoxLayout()
        self.contentsVLO.setAlignment(QtCore.Qt.AlignTop)
        self.setLayout(self.contentsVLO)
    
    def dragEnterEvent(self, event):
        if event.mimeData().hasText():
            event.setDropAction(QtCore.Qt.CopyAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasText():
            cardSource=event.source()
            cardText=cardSource.text()
            if not cardSource in self.children():
                newCard = InitialCard(cardText, self)
                self.contentsVLO.addWidget(newCard)
                cardSource.clear()
            else:
                event.ignore()
        else:
            event.ignore()

class MainDialogue(QtGui.QDialog):
    def __init__(self, parent=None):
        super(MainDialogue, self).__init__(parent)
        self.label=InitialCard("initial", self)
        self.lineEdit=QtGui.QLineEdit("Create a Card Here!!")
        self.lineEdit.selectAll()
        self.scrollArea = QtGui.QScrollArea()
        self.scrollArea.setWidgetResizable(True)
        self.scrollContent = CardsDropWidget(self.scrollArea)
        self.scrollArea.setMinimumWidth(150)
        self.scrollArea.setWidget(self.scrollContent)
        self.dialogueLayout=QtGui.QHBoxLayout()
        self.labelLayout=QtGui.QVBoxLayout()
        self.labelLayout.addWidget(self.label)
        self.labelLayout.addWidget(self.lineEdit)
        self.labelLayout.addStretch()
        self.dialogueLayout.addWidget(self.scrollArea)
        self.dialogueLayout.addLayout(self.labelLayout)
        self.setLayout(self.dialogueLayout)
        self.setWindowTitle("Drag and Drop")
        self.setMinimumSize(300, 150)
        self.lineEdit.returnPressed.connect(self.createCardTxt_fn)
        
    def createCardTxt_fn(self):
        cardTxt=unicode(self.lineEdit.text())
        self.label.setText(cardTxt)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MainDialogue()
    window.show()
    sys.exit(app.exec_())