2016-11-01 2 views
1

Ich erhalte eine Meldung: "Python funktioniert nicht mehr", wenn ich ein Bild in ein QLabel in einem bereits sichtbaren Fenster lade. Auswählen von Debug-Shows: In Python.exe trat eine nicht behandelte Win32-Ausnahme auf.Python3 + Pillow + QT5: Absturz, wenn ich die Größe eines Labels mit einem Bild ändere

Wenn ich das Bild in das Etikett vor dem Anzeigen des Fensters laden, wird es korrekt angezeigt.

Hier ist die abgespeckte Code:

#!/usr/bin/etc python 
import sys 
import os 
import stat 
from PyQt5.QtCore import * 
from PyQt5.QtGui import * 
from PyQt5.QtWidgets import * 
from PIL import * 
from PIL.ImageQt import * 

def update(label): 
    filename = r"C:\Users\me\Pictures\images\00000229.jpg" 
    im1 = Image.open(filename) 
    print ("Read ({},{})".format(im1.width, im1.height)) 
    im2 = im1.rotate(90, expand=True) 
    print("Rotate ({},{})".format(im2.width, im2.height)) 

    im2.thumbnail((1200,1200)) 
    print("Thumbnail({},{})".format(im2.width, im2.height)) 

    qimage = ImageQt(im2) 
    pixmap = QPixmap.fromImage(qimage) 
    label.setPixmap(pixmap) 


app = QApplication(sys.argv) 

desktop = QDesktopWidget() 
deskGeometry = desktop.availableGeometry() 
print("desktop ({},{})".format(deskGeometry.width(), deskGeometry.height())) 

window = QFrame() 
# If you let QT pick the sizes itself, it picks dumb ones, then complains 
# 'cause they are dumb 
window.setMinimumSize(300, 200) 
window.setMaximumSize(deskGeometry.width(), deskGeometry.height()) 

label = QLabel() 
#call update here: no crash 

caption = QLabel() 
caption.setText("Hello world") 

box = QVBoxLayout() 
box.addWidget(label) 
box.addWidget(caption) 
#call update here, no crash 
window.setLayout(box) 
#call update here, no crash 

window.show() 
#this call to update results in a crash 
update(label) 

#window.updateGeometry() 
print("App: exec") 
app.exec_() 

Ausgang:

desktop (3623,2160) 
Read (1515,1051) 
Rotate (1051,1515) 
Thumbnail(832,1200) 
App: exec 

Muss ich besondere, etwas zu tun QT zu sagen, dass die Fenstergröße ändern wird? Irgendwelche Vorschläge zur Diagnose des Problems von hier ...


Update:

Wenn ich den Körper der Update-Funktion und fügen Sie ihn anstelle des Anrufs kopieren zu aktualisieren, es nicht lange Abstürze - es funktioniert wie erwartet.

Daraus schließe ich, dass es ein Objekt-Lebensdauer-Problem gibt. Irgendwo hinter den Kulissen behält QT und/oder Pillow einen Zeiger auf einen internen Puffer, anstatt eine Kopie zu erstellen oder den Puffer zu "stehlen". Wenn das Objekt der Puffer, der gelöscht wird der Zeiger ungültig und „Bad Things Happen [TM]“

nun zu bestimmen, wer faul ist ...

+0

ich werde wurde Ich schlage vor, dass Sie einen Verweis auf die zugrunde liegenden Bilddaten behalten müssen - aber dann konnte ich das Problem nicht selbst reproduzieren. Aber irgendwie sind diese Arten von Müllsammlungsproblemen bekannt, also glaube ich nicht, dass es irgendetwas gibt Ungewöhnlich geht es hier weiter .. – ekhumoro

+0

'' Wenn ich Probleme mit der Objektlebensdauer haben wollte, würde ich Programm in C++ statt Python - Sheesh. ' 'Danke, dass Sie sich das Problem angesehen haben. –

Antwort

0

ich eine Lösung auf der Beobachtung im Update erwähnt gefunden basierend dass dies ein lebenslanges Objekt zu sein schien.

Ändern der Linie in der update Funktion von

pixmap = QPixmap.fromImage(qimage) 

zu

pixmap = QPixmap.fromImage(qimage).copy() 

erzwingt eine Kopie der Pixmap. Diese Kopie hat anscheinend ihren eigenen Datenpuffer, anstatt den Puffer aus dem Image auszuleihen.

Das Label behält dann einen Verweis auf die Pixmap - die Lebensdauer des Puffers sicherzustellen. Der 'Fehler' scheint zu sein, dass QPixmap.fromImage einen Zeiger auf die Daten im Bild erfasst, aber keinen Verweis auf das Bild behält, wenn das Bild Müll sammelt (was wahrscheinlich ist, weil es ein großes Objekt ist, das Label (und die Pixmap) einen Zeiger auf nicht zugewiesenen Speicher.

[Dieser ‚Zeiger auf den Puffer‘ Zeug reine Spekulation meinerseits, aber das Endergebnis ist, das Programm stürzt nicht mehr ab.]

Verwandte Themen