QML:如何将文件从资源管理器拖到我的 Qt Quick 应用程序?

QML: How to drag file from explorer to my Qt Quick application?

我正在 运行在桌面 Linux (KDE) 上安装 QML 应用程序。当文件被拖放到 QML 应用程序的主 window 上时,我需要获取文件路径和文件名作为文本(带或不带前缀 "file:///")。

如果我将文件从 Dolphin 文件管理器拖到 Firefox 的地址栏,文本 URI(例如,"file:///home/user/Downloads/file.txt")将被放入地址栏并在 Firefox 中打开该文件。这表明文件的拖动信息可从 OS 获得。

我可以使用我构建的 QML 应用程序(下面提供的代码)进行的另一项测试是 select 一些文本(比如在网页上)并将 selection 拖到我的应用程序的主 window。这有效,应用程序获取并存储文本 selection 包含的任何内容。

但是,我无法将 文件 拖放到我的 QML 应用程序中。我不明白为什么我可以拖动文本 selection 但不能拖动文件。我正在提供我的代码的工作示例。

在 KDE 上进行测试,当我将文件拖放到 QML 应用程序 window 上时,会调用 onDropped 方法。在那里我做了一个 console.log 并且 drop.textempty (并且 drag.source 是空的)。

应该如何实现将文件(例如,从文件管理器)拖放到 QML 应用程序?

和 QML:

import QtQuick.Window 2.2
import QtQuick 2.2
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.0

ApplicationWindow {
    id: rootId
    visible: true
    title: "Drag Drop MRE"
    property int margin: 16
    minimumWidth: 600
    minimumHeight: 480

FileDialog {
        id: fileDialog
        title: "Choose File Attachment"
        folder: shortcuts.home
        onAccepted: {
            attachments.text += fileDialog.fileUrls + '\n'
            console.log("added attachment: " + fileDialog.fileUrls)
        }
    }
    DropArea{
    id: drop
    enabled: true
    anchors.fill: parent
    anchors.margins: margin
    Rectangle {
        anchors.fill: parent
        color: "green"
        visible: parent.containsDrag
    }
    onEntered: console.log("entered DropArea")
    onDropped:{
        attachments.text += drop.text + '\n'
        console.log("added attachment: " + drop.text)
        console.log("drag.source: " + drag.source)
    }
    Drag.dragType: Drag.Automatic
    GridLayout {
        id: mainLayout
        anchors.fill: parent
        anchors.margins: margin

        Label {
            text: "Drag Drop MRE"
            font.pixelSize: 16
            Layout.row: 1
            Layout.column: 1
        }

        GroupBox {
            Layout.row: 2
            Layout.column: 1
            id: gridBox
            Layout.fillWidth: true

            GridLayout {
                id: gridLayout
                rows: 1
                flow: GridLayout.TopToBottom
                anchors.fill: parent

                Label { text: "Attached files"
                }

                TextArea {
                    id: attachments
                    Layout.fillWidth: true
                    implicitHeight: 300
                }
            }
        }

        GroupBox {
            Layout.row: 3
            Layout.column: 1
            id: rowBox
            Layout.fillWidth: true
            Row {
                anchors.right: parent.right
                id: rowLayout
                Button {
                    id: attach_button
                    text: "Attach"
                    onClicked: fileDialog.open();

                }
                Button {
                    id: save_button
                    text: "Save"
                    onClicked: console.log(attachments.text)
                }
                Button {
                    id: exit_button
                    text: "Exit"
                    onClicked: Qt.quit()
                }
            }
        }

    }} // Grid Layout & Drop Area
}

我找到了一个相关的问题,但是是反过来的: Drag file from application to explorer. Can my application do the copying?

我还构建了 运行 Qt 示例。不幸的是,这些示例遇到了同样的问题,因此它们对解决问题没有帮助。但是,我已经读到我正在尝试做的事情是可以完成的。我只是还没有找到可行的解决方案。

这应该有效(在 Windows 上测试):

Window {
    id: root
    visible: true
    width: 640
    height: 480
    title: qsTr("Drop Area")

    DropArea {
        id: dropArea;
        anchors.fill: parent
        onEntered: {
            root.color = "gray";
            drag.accept (Qt.LinkAction);
        }
        onDropped: {
            console.log(drop.urls)
            root.color = "white"
        }
        onExited: {
            root.color = "white";
        }
    }
}

在 Qt 6 中,使用 JavaScript 带形式参数的函数。

Window {
    id: root
    visible: true
    width: 640
    height: 480
    title: qsTr("Drop Area")

    DropArea {
        id: dropArea;
        anchors.fill: parent
        onEntered: (drag) => {
            root.color = "gray";
            drag.accept (Qt.LinkAction);
        }
        onDropped: (drop) => {
            console.log(drop.urls)
            root.color = "white"
        }
        onExited: {
            root.color = "white";
        }
    }
}

Parameter "drop" is not declared. Injection of parameters into signal handlers is deprecated. Use JavaScript functions with formal parameters instead.

参考:https://doc.qt.io/qt-6/qml-qtquick-droparea.html