`mime.hasImage()` returns `true` 但是 `mime.imageData()` returns `None` 在 Linux

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

我正在尝试运行在Linux上做一个简单的PyQt5应用,代码如下:

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

在 运行 之前,我将一张图片复制到剪贴板,所以 mime.hasImage() 应该 return True。没问题,也是这样的。但奇怪的是,mime.imageData()有时returns None。那不应该发生。 mime.imageData() 应该包含我复制的图像而不是 None。代码有问题吗?

顺便说一下,这似乎只发生在 Linux,mime.imageData() 从来没有发生在 return None Windows。我正在使用 python3

hasImage() returns True 并不意味着 imageData() returns 一个 QImage 因为它只表示用户将图像复制到剪贴板,并且在什么复制图像的格式?好吧,它可以是 png、jpg 等,也可以提供 url 供客户端应用程序下载或 html 将其插入客户端应用程序,然后通过渲染 [=20] 获取图像=].

所以一般来说,复制图像的应用程序负责发送格式,并且该格式没有限制性标准,但有通用格式。

以下示例显示了处理来自 urls 和 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()