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.

Load an animated gif from a stream and show in PyQt.

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 2020-08-03.
Questions regarding this artice? You can send them to the address below.