PySide2+Pillowでコード-1073740771 (0xC000041D)エラー
前の記事ではwxPythonが~PyQtが~って言ってたんですが結局PySide2やってます。
ほとんどPyQt5と違いは無いらしいけど、ライセンスがLGPLなのでちょっと安心かなと
(あまり皆気にしてないような気もする)
2020/12/20追記
PySide2で開発してて、こんな感じでエラーコードしか出なくて詳しいエラーがわからなくなったとき
もしPyCharm等のIDEから実行してる場合は一度素のpythonインタプリタから実行してみると文字列でエラーが出る時がある。
あと大抵はオブジェクトが勝手に破棄されるエラーのような気も。
PySide2関連のオブジェクトを作ったらとりあえずコンストラクタのparent(QObjectを継承してるなら必ずある)を設定して親子関係にしてあげるか、クラスのメンバとして保持してあげる。
QThreadを作ってjoinしないで実行しっぱなしだからってparentにも設定しないメンバにも持たないさようなら~だと死。
本題
で、タイトルの通り…
Pillowを使って画像をいじり、QPixmapでPySide2のGUI画面上に表示しようとしたら
コード-1073740771 (0xC000041D)でエラーになりました。
結論から言うと、QPixmapを作るときにcopyするとOKでした。
こうしていたのを
#image: PIL.Image
qtimg = ImageQt(image)
pixmap = QPixmap.fromImage(qtimg)
こう。
#image: PIL.Image qtimg = ImageQt(image) pixmap = QPixmap.fromImage(qtimg).copy() #★copy
ここの回答ほぼまんまで解決しましたが、エラー内容は違うかな…?
stackoverflow.com
下で書きますが、QGraphicsViewあたりもいじってたので原因特定がちょっと大変でした…
具体例(半分雑記)
PillowのImageGrabでスクリーンショットを撮って
PySide2のQGraphicsViewに表示させよう~としたらハマりました。
再現できるコードはコチラ。
#main_form_ui.py #UI部分のみ from PySide2 import QtCore, QtGui, QtWidgets class Ui_MainForm(object): def setupUi(self, MainForm): MainForm.setObjectName("MainForm") MainForm.resize(400, 300) self.horizontalLayout = QtWidgets.QHBoxLayout(MainForm) self.horizontalLayout.setObjectName("horizontalLayout") #QGraphicsViewを配置 self.viewMain = QtWidgets.QGraphicsView(MainForm) self.viewMain.setObjectName("viewMain") self.horizontalLayout.addWidget(self.viewMain) self.retranslateUi(MainForm) QtCore.QMetaObject.connectSlotsByName(MainForm) def retranslateUi(self, MainForm): MainForm.setWindowTitle(QtWidgets.QApplication.translate("MainForm", "Dialog", None, -1))
#main_form.py #フォームの実装とmain from PySide2.QtWidgets import QApplication, QMainWindow, QDialog, QGraphicsScene,QGraphicsPixmapItem from PySide2.QtGui import QPixmap from PIL import Image, ImageGrab from PIL.ImageQt import ImageQt from main_form_ui import Ui_MainForm import sys class MainForm(QDialog): def __init__(self,parent=None): super().__init__(parent) self.ui = Ui_MainForm() self.ui.setupUi(self) scene = QGraphicsScene(None) #スクリーンショットを取得、QGraphicsPixmapItemになるまで変換してsceneに追加 image = ImageGrab.grab() imgqt = ImageQt(image) #★ココ! pixmap = QPixmap.fromImage(imgqt)#.copy() pixmap_item = QGraphicsPixmapItem(pixmap) scene.addItem(pixmap_item) self.ui.viewMain.setScene(scene) if __name__ == "__main__": app = QApplication(sys.argv) window = MainForm() window.show() sys.exit(app.exec_())
ウィンドウにQGraphicsViewが貼ってあって、そこに起動時にImageGrabで撮ったスクショを貼るだけのコードです。
問題の箇所は★ココ!の部分で、ImageGrabで取得したスクショ画像をQPixmapにするところですね。
ちなみにImageGrabではなく、Image.openで画像ファイルを開いたものを渡したときはQPixmapをcopyしなくても動作していました。
StackOverflowの回答にあるように、特定状況でリソースが解放されてしまう感じなんでしょうか。