当我的PyQt窗口变为非活动状态/调整大小时,为什么Python会崩溃?

时间:2017-09-26 20:44:24

标签: python-2.7 crash pyqt4 qpainter python-imageio

在PyQt4窗口中使用不同的方式来显示网络摄像头源(使用imageio / ffmpeg获得)时,我偶然发现了this answer。在Python 2.7中将其作为include?类实现(如下所述),一切似乎都运行正常:打开一个窗口,显示我的网络摄像头源没有故障。如果我关上窗户,一切都会停止并整齐地关闭。

但是......每当我点击这个PyQt窗口外的任何地方(当它显示网络摄像头时),导致它失去焦点,Python.exe会因未处理的win32异常而崩溃。当我尝试调整窗口大小时会发生同样的情况。

我可能犯了某种极其愚蠢的初学者错误,但我只是没有看到它。谁能指出我正确的方向?我打破了(Py)Qt甚至Python的一些基本规则吗?

这是一个最小的例子:

ImageDisplayWidget

我发现可以通过添加import sys import numpy from PIL import Image, ImageQt # pillow from PyQt4 import QtGui, QtCore class DummyVideoGrabber(QtCore.QTimer): signal_image_available = QtCore.pyqtSignal(QtGui.QImage) def __init__(self): super(DummyVideoGrabber, self).__init__() self.timeout.connect(self.update_image) self.counter = 0 def update_image(self): # Dummy rgb image (in reality we get a numpy array from imageio's Reader) self.counter += 1 numpy_image = numpy.zeros(shape=(480, 640, 3), dtype=numpy.int8) numpy_image[:, :, self.counter%3] = 255 qt_image = ImageQt.ImageQt(Image.fromarray(numpy_image, mode='RGB')) # Emit image self.signal_image_available.emit(qt_image) class ImageDisplayWidget(QtGui.QWidget): """ Custom widget that displays an image using QPainter. Mostly copied from: https://stackoverflow.com/a/22355028/4720018 """ def __init__(self, size_wxh=None, parent=None): super(ImageDisplayWidget, self).__init__(parent) self.image = QtGui.QImage() def set_image(self, qimage, resize_window=False): self.image = qimage self.repaint() def paintEvent(self, QPaintEvent): if not self.image: return painter = QtGui.QPainter(self) painter.drawImage(self.rect(), self.image, self.image.rect()) app = QtGui.QApplication(sys.argv) # instantiate a display object display = ImageDisplayWidget() display.resize(640, 480) display.show() # instantiate a grabber object grabber = DummyVideoGrabber() grabber.signal_image_available.connect(display.set_image) grabber.start(100) # timer interval in ms # start the event loop app.exec_() 标志(在构造函数中初始化为wasActiveWindow)并将True调用封装在某些逻辑中来阻止崩溃:

drawImage()

但是,调整窗口大小仍然会导致python崩溃。

1 个答案:

答案 0 :(得分:2)

通过将qt_image的引用保持为self.qt_image来解决问题:

...
# Emit image
self.qt_image = ImageQt.ImageQt(Image.fromarray(numpy_image, mode='RGB'))
self.signal_image_available.emit(self.qt_image)
...    

这种方式可以正常工作。不再需要self.wasActiveWindow解决方法。

仍然不确定为什么保留引用会导致低级别的python崩溃...