pythonpython-3.xpyqtpyqt5qpixmap

How to pickle QPixmap object dict in Python 3


I want to pickle QPixmap object dict in Python 3

For example,

ImageQpixmapDict = {}
ImageQpixmapDict['XXX'] = QPixmap() 

In this situation, I want to pickle ImageQpixmapDict variable

like

pickle.dump(ImageQpixmapDict, 'filePath')

I tried to pickle QPixmap object by using QSettings, but it doesn't work.

But as you know, QPixmap object couldn't be pickled. So, How can I solve this problem.


Solution

  • Only some Qt classes are pickable (see the docs) and among them there is no QPixmap so a solution is to create a derived class that implements that logic:

    import pickle
    from PyQt5 import QtCore, QtGui
    
    
    class Pickable_QPixmap(QtGui.QPixmap):
        def __reduce__(self):
            return type(self), (), self.__getstate__()
    
        def __getstate__(self):
            ba = QtCore.QByteArray()
            stream = QtCore.QDataStream(ba, QtCore.QIODevice.WriteOnly)
            stream << self
            return ba
    
        def __setstate__(self, ba):
            stream = QtCore.QDataStream(ba, QtCore.QIODevice.ReadOnly)
            stream >> self
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtGui.QGuiApplication(sys.argv)
    
        # create QPixmap
        pixmap = QtGui.QPixmap(100, 100)
        pixmap.fill(QtGui.QColor("red"))
    
        with open("data.pickle", "wb") as f:
    
            image_dict = dict()
            image_dict["XXX"] = Pickable_QPixmap(
                pixmap
            )  # convert QPixmap to Pickable_QPixmap
            pickle.dump(image_dict, f)
    
        with open("data.pickle", "rb") as f:
            image_dict = pickle.load(f)
            pixmap = image_dict["XXX"]
    
            qpixmap = QtGui.QPixmap(pixmap)  # convert Pickable_QPixmap to QPixmap
    
            assert qpixmap.size() == pixmap.size() == QtCore.QSize(100, 100)
            assert qpixmap.toImage() == pixmap.toImage()