This advertisement helps me to keep writing articles on this website

Load an animated gif from a stream and show in PyQt

With QMovie it is very easy to load an animated gif from a path. But how can you load the animation from a stream? Learn how to use a binary stream, QMovie and Qlabel to show animated gifs in Python

Animated gif

Option 1: All in one script. No subclassing

Here is the code in a single file. If you just want to know how to load a binary stream from a file and feed it to a QMovie object, copy the code and you are done:

import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QLabel
from PyQt5.QtGui import QMovie
from PyQt5.QtCore import QByteArray
from PyQt5.QtCore import QBuffer

app = QApplication(sys.argv)
window = QMainWindow()
window.setWindowTitle("Hello Cubes!")
label = QLabel()
window.setCentralWidget(label)

file = open("cube.gif", "rb")
ba = file.read()
buffer = QBuffer()
buffer.setData(ba)
movie = QMovie(buffer, QByteArray())
label.setMovie(movie)
label.setMargin(20)
window.show()
movie.start()
app.exec_()

Option 2: Subclassed QWindow

If you subclass QWindow, QGridLayout or any other container controls, the code above will lead to this error:

Segmentation fault: 11

A Segmentation fault indicates a memory problem like an acccess violation. You can fix this problem when you make the buffer an attribute of the Window. To do this, prefix buffer with self. like this:

self.buffer = QBuffer()
self.buffer.setData(ba)
movie = QMovie(self.buffer, QByteArray())

Subclassed QWindow example

Here is a complete example where QWindow is subclassed. It loads a stream and shows it through a QMovie in a QLabel:

import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QLabel
from PyQt5.QtGui import QMovie
from PyQt5.QtCore import QByteArray
from PyQt5.QtCore import QBuffer


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Hello Cubes!")
        label = QLabel()
        self.setCentralWidget(label)
        file = open("cube.gif", "rb")
        ba = file.read()
        self.buffer = QBuffer()
        self.buffer.setData(ba)
        movie = QMovie(self.buffer, QByteArray())
        label.setMovie(movie)
        label.setMargin(20)
        movie.start()


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

Option 3: Subclassed and loaded from BytesIO

if your stream is a BytesIO stream, you need to convert the stream to a QByteArray first. Here is the complete example:

import sys
import io
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QLabel
from PyQt5.QtGui import QMovie
from PyQt5.QtCore import QByteArray
from PyQt5.QtCore import QBuffer


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Hello Cubes!")
        label = QLabel()
        self.setCentralWidget(label)
        file = open("cube.gif", "rb")
        stream = io.BytesIO(file.read())
        byte_array = QByteArray(stream.read())
        self.buffer = QBuffer()
        self.buffer.setData(byte_array)
        movie = QMovie(self.buffer, QByteArray())
        label.setMovie(movie)
        label.setMargin(20)
        movie.start()


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
Written by Loek van den Ouweland on August 03, 2020. Questions regarding this artice? You can send them to the address below.
By using this site, you acknowledge that you have read and understand our Cookie and Privacy Policy.