Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
443 views
in Technique[技术] by (71.8m points)

python - `mime.hasImage()` returns `true` but `mime.imageData()` returns `None` on Linux

I'm trying to run a simple PyQt5 application on Linux, the code is as follows:

#!/usr/bin/python

import sys
from PyQt5.QtWidgets import QApplication, QWidget


def main():
    app = QApplication(sys.argv)

    w = QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple')
    w.show()

    mime = app.clipboard().mimeData()
    print(mime.hasImage())  # True
    print(mime.imageData())  # None

    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

Before running it, I copied an image into the clipboard, so mime.hasImage() should return True. No problem, that's also the case. But what's weird is, mime.imageData() sometimes returns None. that shouldn't happen. mime.imageData() should contain the image that I copied instead of None. Is there anything wrong with the code?

By the way, this seems to only happen on Linux, mime.imageData() never returns None on Windows. I'm using python3

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

That hasImage() returns True does not imply that imageData() returns a QImage since it only indicates that the user copied an image to the clipboard, and in what format do I copy the image? Well, it could be png, jpg, etc or it could provide the url for the client application to download or html to insert it into the client application and then obtain the image by rendering the HTML.

So in general the application from which the image was copied is responsible for the sending format and that there is no restrictive standard for that format but there are common formats.

The following example shows the logic to handle the images that come from urls and HTML:

#!/usr/bin/python

import sys
from functools import cached_property

from PyQt5.QtCore import pyqtSignal, QObject, QUrl
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
from PyQt5.QtGui import QGuiApplication, QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QLabel

from bs4 import BeautifulSoup


class ImageDownloader(QObject):
    finished = pyqtSignal(QImage)

    def __init__(self, parent=None):
        super().__init__(parent)

        self.manager.finished.connect(self.handle_finished)

    @cached_property
    def manager(self):
        return QNetworkAccessManager()

    def start_download(self, url):
        self.manager.get(QNetworkRequest(url))

    def handle_finished(self, reply):
        if reply.error() != QNetworkReply.NoError:
            print("error: ", reply.errorString())
            return
        image = QImage()
        image.loadFromData(reply.readAll())
        self.finished.emit(image)


class ClipboardManager(QObject):
    imageChanged = pyqtSignal(QImage)

    def __init__(self, parent=None):
        super().__init__(parent)

        QGuiApplication.clipboard().dataChanged.connect(
            self.handle_clipboard_datachanged
        )

        self.downloader.finished.connect(self.imageChanged)

    @cached_property
    def downloader(self):
        return ImageDownloader()

    def handle_clipboard_datachanged(self):
        mime = QGuiApplication.clipboard().mimeData()
        if mime.hasImage():
            image = mime.imageData()
            if image is not None:
                self.imageChanged.emit(image)
            elif mime.hasUrls():
                url = mime.urls()[0]
                self.downloader.start_download(urls[0])
            elif mime.hasHtml():
                html = mime.html()
                soup = BeautifulSoup(html, features="lxml")
                imgs = soup.findAll("img")
                if imgs:
                    url = QUrl.fromUserInput(imgs[0]["src"])
                    self.downloader.start_download(url)
            else:
                for fmt in mime.formats():
                    print(fmt, mime.data(fmt))


def main():
    app = QApplication(sys.argv)

    label = QLabel(scaledContents=True)
    label.resize(250, 150)
    label.move(300, 300)
    label.setWindowTitle("Simple")
    label.show()

    manager = ClipboardManager()
    manager.imageChanged.connect(
        lambda image: label.setPixmap(QPixmap.fromImage(image))
    )

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...