拒绝在DropArea中拖动的外部文件,而不会破坏DropArea

时间:2014-04-01 13:23:13

标签: qml qtquick2

在我的应用程序中,我正在显示音频文件列表,用户可以拖动外部文件将其添加到列表中。如果我的应用程序不支持列表中的文件,我希望能够拒绝拖动。

问题是,当我在drag.accepted = false;的{​​{1}}中拨打onEntered时,它会对任何其他事件完全没有回应。

以下是一些显示问题的示例代码。如果您在窗口中拖动MP3,您会看到它有效。然后,如果您拖动任何其他文件,它将无法正常工作,如预期。但是,拖回DropArea文件也不起作用。

MP3

import QtQuick 2.1 import QtQuick.Window 2.0 ApplicationWindow { title: qsTr("Hello World") width: 640 height: 480 DropArea { anchors.fill: parent onEntered: { console.log("[Droparea] entered"); // Ensure at least one file is supported before accepted the drag var validFile = false; for(var i = 0; i < drag.urls.length; i++) { if(validateFileExtension(drag.urls[i])) { validFile = true; break; } } if(!validFile) { console.log("No valid files, refusing drag event"); drag.accepted = false; return false; } } onExited: { console.log("[Droparea] entered"); } onDropped: { console.log("[Droparea] dropped"); } // Only MP3s function validateFileExtension(filePath) { var extension = filePath.split('.').pop(); var valid = false; if(extension == "mp3") { valid = true; } return valid; } } Text { id: textDrop anchors.centerIn: parent text: "Please drag element" } } 中是否有错误或者我误解了什么?我知道我可以过滤onDropped中的文件,但是当你在不接受它们的区域上拖动文件时,你会失去在OSX上获得的视觉反馈。

2 个答案:

答案 0 :(得分:6)

很长一段时间都是known bug。已经提交了一个补丁,经过几个月的停顿后现在merged into 5.6 branch


任何想要使用此功能的人都必须升级到Qt 5.6或MANULLY将可用的补丁集成到他/她的Qt版本中。


DropArea中包含的

QQuickDropAreaPrivate会在true发生时将containsDrag标记更新为dragEnterEvent,并发出entered信号。当containsDrag发生时,它会false更新为dragLeaveEvent,并发出exited信号。但是,当不接受拖动事件时,永远不会调用dragLeaveEvent,从而使私有对象处于不存在状态。由于dragEnterEvent仍为containsDrag,因此之后的每个true都会被丢弃,即之前的拖动事件仍然被视为有效且entered不再发出。

由于该问题与私有API和公共API的使用之间的交互有关,因此问题不会影响使用keys的过滤。不幸的是,这种方法似乎不适合所提出的用例。

相当部分的解决方法是使用MouseAreaDropArea。当拒绝发生时,后者会自动禁用,而前者会在下一次丢弃时返回DropArea。此解决方法涵盖了一个常见情况,其中内部 DropArea中删除了错误的项目,这对最终用户来说是最常见和最直观的。释放错误的项之外DropArea使机制失效(直到下一次丢弃)。

以下是代码:

import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Window 2.0

ApplicationWindow {
    title: qsTr("Hello World")
    width: 640
    height: 480
    visible: true

    MouseArea {
        anchors.fill: parent
        hoverEnabled: true
        enabled: !drop.enabled
        onContainsMouseChanged: drop.enabled = true
    }

    DropArea {
        id: drop
        anchors.fill: parent

        onEntered: {
            console.log("[Droparea] entered");
            // Ensure at least one file is supported before accepted the drag
            for(var i = 0; i < drag.urls.length; i++)
                if(validateFileExtension(drag.urls[i]))
                    return
            console.log("No valid files, refusing drag event")
            drag.accept()
            drop.enabled = false
        }

        onExited: console.log("[Droparea] exited")

        onDropped: console.log("[Droparea] dropped")

        // Only MP3s
        function validateFileExtension(filePath) {
            return filePath.split('.').pop() == "mp3"
        }
    }

    Text {
        id: textDrop
        anchors.centerIn: parent
        text: "Please drag element"
    }
}

答案 1 :(得分:-1)

你永远不会被接受=真实

在将有效设置为有效

后添加drag.accepted = true
for(var i = 0; i < drag.urls.length; i++) {
    if(validateFileExtension(drag.urls[i])) {
      validFile = true;
      drag.accepted = true;
      break;
    }
  }