如何获得从浏览器拖放到DropArea QML组件的图像



我使用DropArea组件使用拖放机制将文件传输到我的应用程序。下面的测试代码可以很好地处理系统上的文件:

import QtQuick 2.15
import QtQuick.Window 2.15
Window {
    id: root
    width: 640
    height: 480
    visible: true
    DropArea {
        id: dropArea
        anchors.fill: parent
        onEntered: {
            drag.accepted = drag.hasUrls
        }
        onDropped: {
            // Use files through drop.urls
            drop.accept()
        }
    }
}

onEntered中,如果包含url,我接受DragEvent,而在onDropped中,我可以使用url来处理删除的文件。

但我也需要通过DropArea接受来自浏览器的图像。同时,由于从浏览器中拖出的图像在文件系统中不存在,因此我希望接收原始图像数据,以便我自己创建图像文件。

问题是来自dropped信号的DragEvent drop没有这样的数据。这可以通过以下日志来验证:

onDropped: {
    console.log("drop.urls: " + drop.urls)
    console.log("drop.html: " + drop.html)
    console.log("drop.text: " + drop.text)
    console.log("-----------------------")
    for (var i = 0; i < drop.formats.length; ++i) {
        console.log(drop.formats[i] + ": " + drop.getDataAsString(drop.formats[i]))
    }
}

将给出以下信息(从文档中拖放Qt徽标图像):

qml: drop.urls: https://doc.qt.io/
qml: drop.html: <html>
<body>
<!--StartFragment--><img src="https://doc.qt.io/style/qt-logo-documentation.svg" alt="Qt documentation"><!--EndFragment-->
</body>
</html>
qml: drop.text: https://doc.qt.io/
qml: -----------------------
qml: application/x-qt-windows-mime;value="DragContext": 
qml: application/x-qt-windows-mime;value="DragImageBits": ?
qml: application/x-qt-windows-mime;value="chromium/x-renderer-taint": 
qml: application/x-qt-windows-mime;value="FileGroupDescriptorW": 
qml: application/x-qt-windows-mime;value="FileContents": 
qml: text/x-moz-url: h
qml: text/uri-list: https://doc.qt.io/
qml: application/x-qt-windows-mime;value="UniformResourceLocatorW": h
qml: text/plain: https://doc.qt.io/
qml: text/html: <html>
<body>
<!--StartFragment--><img src="https://doc.qt.io/style/qt-logo-documentation.svg" alt="Qt documentation"><!--EndFragment-->
</body>
</html>

在可用属性中(包括通过格式获得的属性),没有原始图像数据。drop.html提供了关于被删除图像的地址的有用信息,但是获取图像的唯一方法是使用接收到的链接下载它吗?

我还考虑是否有可能以某种方式获得QMimeData,以便它可以调用imageData()并以这种方式获取图像。我发现类似的mime数据传输到QML从Krita开发人员(见declaratiemimedata * const m_data,他们定义为Q_PROPERTY),但我不确定这是最简单的,最重要的,工作方式。

那么总结一下,是否有一种方法可以使用标准的QML DropArea组件从浏览器或图像本身作为QImage拖放图像的原始数据?

在使用c++和QNetworkAccessManager之前,您可以在QML中做一些额外的事情来验证您是否确实有一个图像。

下面的例子说明我们可以:

  1. 检查drop.formats
  2. 运行XMLHTTPRequest "HEAD"请求

后者特别有用,因为我们可以从内容类型推断mime类型,如果可以的话,还可以通过读取内容长度来确定内容的大小。

另外,如果希望拥有映像的内存副本,可以创建第二个XMLHttpRequest。这次你可以设置"GET"并将responseType设置为"arraybuffer"

            DropArea {
                id: dropArea
                anchors.fill: parent
                property url dropUrl
                property string contentType
                property bool isImage
                property int contentLength
                onDropped: function (drop) {
                    console.log("formats: ", JSON.stringify(drop.formats));
                    if (!drop.hasUrls) return;
                    let xhr = new XMLHttpRequest();
                    dropUrl = drop.urls[0];
                    console.log("dropUrl: ", dropUrl);
                    xhr.open("HEAD", dropUrl, false);
                    xhr.send();
                    contentType = xhr.getResponseHeader("Content-Type");
                    console.log("contentType: ", contentType);
                    isImage = contentType.startsWith("image/");
                    contentLength = xhr.getResponseHeader("Content-Length") ?? 0;
                    console.log("contentLength: ", contentLength);
                    let xhr2 = new XMLHttpRequest();
                    xhr2.open("GET", dropUrl, false);
                    xhr2.responseType = "arraybuffer";
                    xhr2.send();
                    let data = xhr2.response;
                    console.log(data.byteLength);
                }
            }

最新更新