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

koo*_*jah 7 qml qtquick2

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

问题是,当我打电话drag.accepted = false;onEntered我的DropArea则变得完全不响应任何其他事件.

以下是一些显示问题的示例代码.如果你在窗口中拖动MP3,你会发现它有效.然后,如果您拖动任何其他文件,它将无法正常工作,如预期.但是,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"
  }

}
Run Code Online (Sandbox Code Playgroud)

是否有错误DropArea或我误解了什么?我知道我可以过滤onDropped中的文件,但是当你在不接受它们的区域上拖动文件时,你会失去在OSX上获得的视觉反馈.

BaC*_*Zzo 6

很长一段时间它一直是一个已知的bug.已经提交了一个补丁,经过几个月的停滞后现已合并到5.6分支中.


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


QQuickDropAreaPrivate包含DropArea在内,将containsDrag标志更新truedragEnterEvent发生时,发出entered信号.它更新containsDragfalsedragLeaveEvent发生时,发射exited信号.但是,当不接受拖动事件时,dragLeaveEvent永远不会调用,从而使私有对象处于不存在状态.dragEnterEvent因为containsDrag仍然存在true,所以每个后续都被丢弃,即先前的拖动事件仍被认为是活动的并且entered不再发出.

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

一个相当部分的解决方法是使用一个MouseArea与一起DropArea.当拒绝发生时,后者会自动禁用,而前者会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"
    }
}
Run Code Online (Sandbox Code Playgroud)


Blu*_*gma -1

你从来没有把accepteed = true

只需在将 valid 设置为有效后添加 Drag.accepted = true

for(var i = 0; i < drag.urls.length; i++) {
    if(validateFileExtension(drag.urls[i])) {
      validFile = true;
      drag.accepted = true;
      break;
    }
  }
Run Code Online (Sandbox Code Playgroud)