2016-11-01 4 views
1

メッセージボックスが表示されています。既に表示されているウィンドウのQLabelにイメージを読み込むと「Pythonが動作しなくなりました。デバッグショーの選択:Python.exeで未処理のWin32例外が発生しました。Python3 + Pillow + QT5:イメージを含むラベルのサイズを変更するとクラッシュする

ウィンドウを表示する前にイメージをラベルにロードすると、正しく表示されます。

は、ここでストリップダウンコードです:

#!/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_() 

出力:

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

私はQTを教えてウィンドウサイズが変更されることをするために特別な何かをする必要がありますか?ここから問題を診断するための任意の提案...


がアップデート:私は更新関数の本体をコピーし、更新するための呼び出しの代わりに貼り付けた場合、それは長い

をクラッシュしません - 期待どおりに動作します。

これから私は、オブジェクトライフタイムの問題があると結論づけます。舞台裏のどこかで、QTや枕はバッファのコピーや "盗み"を作るのではなく、内部のバッファへのポインタを保持しています。バッファを含むオブジェクトは、ポインタが無効になり削除され、怠けています誰が決定するために今すぐ

「悪いことは[TM]が起こる」...

+0

私が行っていました基本的なイメージデータへの参照を保持する必要があることを示唆していますが、実際に問題を自分で再現することはできませんでしたが、とにかく、これらの種類のガベージコレクションの問題はよく知られているので、珍しいここに行く – ekhumoro

+0

''私はオブジェクトの生涯の問題を欲しかったPythonではなくC++でプログラムを作成します。 ''問題を見ていただきありがとうございます。 –

答えて

0

とき、私は更新で述べた観察に基づいて解決策を見つけましたこれはオブジェクトの生涯の問題であるように見えた

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

pixmap = QPixmap.fromImage(qimage) 

からupdate関数内の行を変更するには、ピックスマップのコピーを強制します。このコピーには、イメージからバッファを借用するのではなく、独自のデータバッファがあるようです。

次に、ラベルはピクスマップへの参照を保持し、バッファの有効期間を保証します。 「バグ」は、QPixmap.fromImageがImage内のデータへのポインタを取得しているが、Imageへの参照を保持していないため、Imageがガベージコレクションされた場合(これは大きなオブジェクトである可能性が高いため、Label (およびピックスマップ)割り当てられていないメモリへのポインタを持っている。

[この「ポインタバッファへの」ものは私の一部に膨大な憶測ですが、一番下の行は、プログラムがクラッシュしなくなりましたではありません。]

関連する問題