【问题标题】:PySide crash when displaying pixmaps显示像素图时 PySide 崩溃
【发布时间】:2016-01-27 10:36:25
【问题描述】:

我正在通过 PySide 使用 Python 和 Qt 编写一个用于数据可视化的 GUI 应用程序。 我偶尔会遇到崩溃('python.exe 已停止工作'),我认为我将其缩小到以下问题:

当从 numpy 数组创建像素图时,即使像素图已经存在,python (?) 也会以某种方式释放内存。 如果使用的图像格式是 QImage.Format_ARGB32,则不会发生这种情况。(为什么不呢?)。查看下面的代码示例,希望您能重现问题。


编辑:澄清 - 如果 numpy 数组没有被 python 删除,一切都按预期工作。但是,在我的应用程序中,新数据不断生成,我必须找到一种好方法来跟踪当前显示为像素图的数据集,并在不再显示时将其删除。我想为 Qt 找到正确的方法来处理(图像)数据并将其存储在内存中,直到不再需要为止。


据我了解QtPySide的文档,像素图应该保存图像的所有数据,因此Qt应该负责内存管理。

这是 Qt、Pyside 中的错误,还是我不明白什么?我在常规文档中找不到有关内存管理的任何详细信息。

背景:我需要定期更新要显示的数据,因此在创建像素图和显示它之间,numpy 数据数组可能已经被 python 覆盖(因为涉及一些 CPU 密集型线程,有时会减慢图形用户界面)。因此,永远存储 numpy 数组不是一种选择。

这是一个代码示例,有趣的部分发生在 display_image 方法中:

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)

我在通用 Windows7 Office PC 上使用 32 位 Python 2.7.6 和 PySide 1.2.2。

感谢您的帮助!

【问题讨论】:

  • 每个“像素”只有一个值。 argb 可以重新整形为 (1024, 1024)。您可能需要(1024、1024、3 或 4)
  • 但它一开始就行不通,不是吗?我很确定 QImage 期望像素值为 32 位值,如 xAARRGGBB
  • 是的,你是对的,我的错
  • 似乎 QImage 只包含对图像的引用。如果您将argb 存储为类变量,则数据不会被垃圾收集,并且图像将正确显示
  • stackoverflow.com/questions/9794019/… 在此处查看 pwuertz 的答案,了解如何让 PySide 管理内存

标签: python qt pyside


【解决方案1】:

这个简单的改变可以防止图像在函数完成时被垃圾回收。这似乎是导致问题的原因

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)

【讨论】:

    猜你喜欢
    • 2019-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-22
    • 2013-07-15
    • 1970-01-01
    • 2015-04-07
    相关资源
    最近更新 更多