82651


ウインドウに画像をドラッグ＆ドロップして表示するだけのプログラムが作りたいのですが、下のコードで実行してローカルの画像を入れると、  
`True False False True False`  
と出力されます。つまり、画像が画像データとして認識されません。どの拡張子の画像でも認識されませんでした。ウェブからのドラッグでも認識されませんでした。おそらくPC側の問題ではないかと思うのですが、よくわかりません。  
同様の質問が見当たらなかったので、非常に初歩的な質問するまでもない問題だと思うのですが、自分にはどうしても原因がわかりません。原因がわかる方、よろしくお願いします。

[code]

    import sys
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    
    class MainWindow(QWidget):
        def __init__(self):
            super().__init__()
            self.setAcceptDrops(True)
            self.vbl = QVBoxLayout()
            self.setLayout(self.vbl)
     
            self.setGeometry(300, 50, 400, 350)
            self.setWindowTitle('QCheckBox')
    
            self.show()
    
        def dragEnterEvent(self, e): 
                e.accept()
        
        def dropEvent(self,e):
            print(e.mimeData().hasText(),e.mimeData().hasHtml(),e.mimeData().hasImage(),e.mimeData().hasUrls(),e.mimeData().hasColor())
            label = QLabel()
            pix = QPixmap(e.mimeData().imageData())
            label.setPixmap(pix)
            self.vbl.addWidget(label)
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        main_window = MainWindow()
        main_window.show()
        app.exec_()
    
[/code]


CC BY-SA 4.0
2021-09-23T06:56:04.853
82647
2021-09-24T07:50:22.803
48333
question
python pyqt5
PyQt5のhasImageメソッドで画像が認識されません


ドロップされたデータから画像のパス名を取り出して、イメージを作成する必要があるのだと思います。  
`dropEvent()`を次のように書き換えればうまくいくと思います。  
※確認したのはWindowsです。

[code]

        def dropEvent(self, e):
            import urllib.request
            print(e.mimeData().hasText(), e.mimeData().hasHtml(), e.mimeData().hasImage(), e.mimeData().hasUrls(),
                  e.mimeData().hasColor())
            label = QLabel()
            path = urllib.request.url2pathname(e.mimeData().urls()[0].path())
            image = QImage(path)
            pix = QPixmap.fromImage(image)
            label.setPixmap(pix)
            self.vbl.addWidget(label)
    
[/code]

Windowsのパス名はドライブ名の先頭に`/`が付加されてしまいます。  
`urllib.request.url2pathname`で削除しています。  
<https://stackoverflow.com/questions/43911052/urlparse-on-a-windows-file-
scheme-uri-leaves-extra-slash-at-start>

* * *

metropolisさんから次のコメントがありました。

> ウェブブラウザから画像をドラッグ・アンド・ドロップする場合、そのコードでは何も表示されないのでご注意を。

このような使い方をすることを全然考えていませんでした。調べてみたところ次の記事を見つけました。  
<https://qiita.com/y-chan/items/7d99a3dc3f1cc55dad6a>  
この記事を参考にしたコードを書いてみたところ、ネット上の画像が表示されました。

[code]

        def dropEvent(self, e):
            if e.mimeData().hasHtml():
                import requests
                import base64
                url = e.mimeData().urls()[0].toString()
                data = base64.b64encode(requests.get(url).content).decode()
                label = QLabel(f"<img src=\"data:image/png;base64,{data}\"/>")
                self.vbl.addWidget(label)
            else:
                import urllib.request
                label = QLabel()
                path = urllib.request.url2pathname(e.mimeData().urls()[0].path())
                image = QImage(path)
                pix = QPixmap.fromImage(image)
                label.setPixmap(pix)
            self.vbl.addWidget(label)
    
[/code]


CC BY-SA 4.0
2021-09-23T12:24:36.780
82651
2021-09-24T06:04:42.463
2021-09-24T06:04:42.463
35558
35558
82647
answer


既に解決済みですが、参考までに別回答を投稿します。

※ `User-Agent` を指定しているのは `HTTP status code 403(Forbidden)` を回避するためのものです

[code]

    import sys
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    from urllib.request import Request, urlopen
    
    class MainWindow(QWidget):
        request_headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0'
        }
    
        def __init__(self):
            super().__init__()
            self.setAcceptDrops(True)
            self.vbl = QVBoxLayout()
            self.setLayout(self.vbl)
     
            self.setGeometry(300, 50, 400, 350)
            self.setWindowTitle('QCheckBox')
    
            self.show()
    
        def dragEnterEvent(self, e): 
            e.accept()
        
        def dropEvent(self,e):
            if e.mimeData().hasImage():
                pix = QPixmap(e.mimeData().imageData())
            elif e.mimeData().hasUrls():
                url = e.mimeData().urls()[0]
                if url.isLocalFile():
                    pix = QPixmap(url.toLocalFile())
                else:
                    # remote file
                    try:
                        req = Request(url.toString(), headers=self.__class__.request_headers)
                        data = urlopen(req).read()
                    except:
                        return
                    pix = QPixmap()
                    pix.loadFromData(data)
                    # (pix := QPixmap()).loadFromData(data)
            else:
                # nothing to do
                return
    
            # return if the iamge file does not exist or is of an unknown format
            if pix.isNull(): return
    
            # clear all widgets in QVBoxLayout
            for i in reversed(range(self.vbl.count())): 
                w = self.vbl.itemAt(i).widget()
                self.vbl.removeWidget(w)
                w.setParent(None)
    
            label = QLabel()
            label.setPixmap(pix)
            self.vbl.addWidget(label)
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        main_window = MainWindow()
        main_window.show()
        app.exec_()
    
[/code]


CC BY-SA 4.0
2021-09-24T07:50:22.803
82659
2021-09-24T07:50:22.803
47127
82647
answer