我使用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中做一些额外的事情来验证您是否确实有一个图像。
下面的例子说明我们可以:
- 检查
drop.formats
- 运行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);
}
}