Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python PyQt pixmap update crashes

I have a simple PyQt application. You can cycle through a folder of images using pageup and pagedown keys.

I am using the pixmap of a QLabel to display the images. The following logic actually works until you comment the processEvents call.

python crash

Any ideas on the cause of the crash and why adding processEvents prevents the crash?

# Python version: 2.7.9 
# Qt version: 4.8.6
# PyQt version: 4.11.3

import sys
import os 
from PIL import Image
from PIL import ImageOps
from PIL.ImageQt import ImageQt
from PyQt4 import QtGui
from PyQt4 import QtCore
from PyQt4 import Qt

imagefolder = "C:/Users/alan/Desktop/imagefolder"

class QExampleLabel (QtGui.QLabel):
    def __init__(self, parentQWidget = None):
        super(QExampleLabel, self).__init__(parentQWidget)
        self.initUI()

    def initUI (self):

        self.imagelist = []

        for path, subdirs, files in os.walk(imagefolder):
            path = path.replace("\\", "/") 
            for file in files:
                base, ext = os.path.splitext(file)
                if ext.lower() == ".jpg":
                    jpg = path + "/" + file
                    self.imagelist.append(jpg)

        self.i = -1

    def keyPressEvent(self, keyevent):
        event = keyevent.key()
        if event == QtCore.Qt.Key_PageUp:
            self.backward()
        if event == QtCore.Qt.Key_PageDown:
            self.forward()

    def forward(self):
        self.i = self.i + 1
        if self.i >= len(self.imagelist):
            self.i = len(self.imagelist) - 1
        self.displayimage()

    def backward(self):    
        self.i = self.i - 1
        if self.i < 0:
            self.i = 0
        self.displayimage()

    def displayimage(self):   
        photo = self.imagelist[self.i]
        img = Image.open(photo)
        mysize = (260,260)
        method = Image.NEAREST if img.size == mysize else Image.ANTIALIAS
        self.cropimage = ImageOps.fit(img, mysize, method = method, centering = (0.5,0.5)) 
        qim = ImageQt(self.cropimage)
        pix = QtGui.QPixmap.fromImage(qim)
        self.setPixmap(pix)  
        QtGui.QApplication.processEvents()  # comment this line to see setPixmap crash

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    myQExampleLabel = QExampleLabel()
    myQExampleLabel.show()
    myQExampleLabel.resize(260,260)
    sys.exit(app.exec_())
like image 949
panofish Avatar asked Jan 28 '26 02:01

panofish


1 Answers

The error is probably caused by garbage-collection, because you are not keeping an explicit reference to the Qt image object. When you create a pixmap from a QImage, the underlying data will remain shared, so use the QImage copy constructor to get an explicit reference, and then keep it alive until the pixmap is no longer needed:

self._img = QtGui.QImage(qim)
pix = QtGui.QPixmap.fromImage(self._img)

UPDATE:

Using the test case, I was able to eliminate the crash by simply keeping a reference to the original ImageQt object:

self.qim = ImageQt(self.cropimage)
pix = QtGui.QPixmap.fromImage(self.qim)
self.setPixmap(pix)

Or, more simply, by using QPixmap.detach():

qim = ImageQt(self.cropimage)
pix = QtGui.QPixmap.fromImage(qim)
pix.detach()
self.setPixmap(pix)
like image 162
ekhumoro Avatar answered Jan 30 '26 16:01

ekhumoro



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!