简体   繁体   中英

PySide crash when displaying pixmaps

I am programming a GUI application for Data visualization using Python and Qt via PySide. I experience occasional crashes ('python.exe has stopped working') which I think I narrowed down to the following problem:

When creating a pixmap from a numpy array, somehow the memory is freed by python (?) even when the pixmap already exists. This does not happen if the image format used is QImage.Format_ARGB32. (Why not?). Check out the code example below, I hope you can reproduce the problem.


EDIT: To clarify - If the numpy array is not deleted by python, everything works just as expected. However, in my application, new data is generated constantly and I would have to find a good way to track which dataset is currently displayed as a pixmap, and delete it as soon as it is not displayed anymore. I would like to find the correct way for Qt to take care of the (image-) data and store it in memory until not required anymore.


As far as I understood the documentation of Qt and PySide , the pixmap should hold all the data of the image, thus Qt should be responsible for the memory management.

Is this a bug in Qt, Pyside, or did I not understand something? I could not find any details on the memory management in the regular documentation.

Background: I need to regularly update the data to display, thus it may happen that between creating the pixmap and displaying it, the numpy data array is already overwritten by python (as there are some CPU intensive threads involved that sometimes slow the GUI). Thus, storing the numpy array forever is not an option.

Here is a code example, the interesting bits happen in the display_image method:

import numpy as np
from PySide import QtCore, QtGui
import sys

class displaywidget(QtGui.QWidget):
    def __init__(self,parent = None):
        super(displaywidget, self).__init__(parent)

        ## set up the GUI elements
        self.setLayout(QtGui.QGridLayout())
        self.view = QtGui.QGraphicsView()
        self.layout().addWidget(self.view)        
        self.scene = QtGui.QGraphicsScene()
        self.view.setScene(self.scene)

        # create a pixmap and display it on the graphicsview
        self.display_image()
    def display_image(self):
        # create image data in numpy array
        size = 1024
        r = np.linspace(0,255, num = size**2, dtype = np.uint32)
        argb = (r<<16) +(255<<24)

        # image should display a black to red shading
        image = QtGui.QImage(argb, size,size, size*4, QtGui.QImage.Format_RGB32)

        ### using ARGB format option does not cause the problem
#        image = QtGui.QImage(argb, size,size, size*4, QtGui.QImage.Format_RGB32)

        pixmap = QtGui.QPixmap.fromImage(image)

        self.scene.addPixmap(pixmap)
        ### when the image data is stored, everything works fine, too
#        self.cache = argb
        ### if only the pixmap and image is stored, the problem still exists
#       self.cache = [pixmap, image]



def main(argv):
    ## create application and main window
    try:
        app = QtGui.QApplication(argv)
        new_qtapp = True
    except:
        new_qtapp = False
    mainwindow = QtGui.QMainWindow()
    mainwindow.setCentralWidget(displaywidget())
    mainwindow.show()
    if new_qtapp:
        sys.exit(app.exec_())
    return mainwindow
if __name__=="__main__":
    w = main(sys.argv)

I am using 32 bit Python 2.7.6 and PySide 1.2.2 on a generic Windows7 Office PC.

Thanks for your help!

This simple change keeps the image from being garbage collected when the function is done. Which seems to be what caused the problem

self.argb = (r<<16) +(255<<24)

# image should display a black to red shading
image = QtGui.QImage(self.argb, size,size, size*4, QtGui.QImage.Format_RGB32)

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM