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

问题是,当我在自己的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"
  }

}
DropArea中是否存在错误,或者我是否误解了某些内容?我知道我可以过滤onDropped中的文件,但是当在不接受文件的区域上拖动文件时,您会失去在OSX上获得的视觉反馈。

最佳答案

很长一段时间以来一直是known bug。补丁已提交,并且停滞了几个月后现在变成merged into 5.6 branch

任何想要使用此功能的人都必须升级到Qt 5.6或MANULLY将可用的补丁程序集成到他/她的Qt版本中。
QQuickDropAreaPrivate中包含的 DropArea 在发生containsDrag时将 true 标志更新为dragEnterEvent,并发出 entered 信号。当出现containsDrag时,它将false更新为dragLeaveEvent,并发出 exited 信号。但是,当不接受拖动事件时,永远不会调用dragLeaveEvent,从而使私有(private)对象处于困惑状态。因为dragEnterEvent仍然是containsDrag,所以每个后续的true都将被丢弃,即,先前的拖动事件仍被认为是 Activity 的,并且entered不再发出。

由于此问题与私有(private)API和公共(public)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"
    }
}

关于qt - 拒绝在DropArea中拖动的外部文件,而不会破坏DropArea,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22787242/

10-11 16:03