拒绝拖入 DropArea 的外部文件而不破坏 DropArea [英] Reject external files dragged in a DropArea without breaking the DropArea

查看:60
本文介绍了拒绝拖入 DropArea 的外部文件而不破坏 DropArea的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my application I'm displaying a list of audio files and the user can drag an external file to add it to the list. I want to be able to refuse the drag if no file in the list is supported by my application.

问题是,当我在 DropAreaonEntered 中调用 drag.accepted = false; 时,它变得完全没有响应任何其他活动.

The issue is that when I call drag.accepted = false; in onEntered of my DropArea then it becomes completely unresponsive to any other event.

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

Here is some sample code showing the issue. If you drag an MP3 in the window you see that it works. Then if you drag any other file it won't work, as expected. But then dragging an MP3 file back will not work either.

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 上获得的视觉反馈.

Is there a bug in the DropArea or did I misunderstood something? I know I can filter the files in the onDropped but then you loose the visual feedback you get on OSX when dragging file on an area that does not accept them.

推荐答案

这是一个已知错误 很长一段时间.一个补丁已经提交,在停滞了几个月之后现在 合并到 5.6分支.

It has been a known bug for a long time. A patch has been submitted and after been stalled for several months is now merged into 5.6 branch.

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

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

QQuickDropAreaPrivate, contained in DropArea, updates the containsDrag flag to true when a dragEnterEvent occurs, emitting the entered signal. It updates containsDrag to false when adragLeaveEvent occurs, emitting an exited signal. However, when the drag event is not accepted dragLeaveEvent is never called, leaving the private object in a incosistent state. Each subsequent dragEnterEvent is discarded since containsDrag is still true, i.e. the previous drag event is still considered active and the entered is no more emitted.

由于该问题与私有 API 和公共 API 的使用之间的交互有关,所以该问题影响使用 keys.不幸的是,这种方法似乎不适合呈现的用例.

Since the issue is related to an interaction between private APIs and usage of the public APIs, the problem does not affect filtering using keys. Unfortunately, this approach does not seem to fit for the presented use case.

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

A quite partial workaround is to use a MouseArea along with the DropArea. The latter disables itself when a rejection occurs while the former enables back the DropArea for the next drop. This workaround covers the common case in which a wrong item is dropped inside the DropArea, which is the most common and intuitive for an end user. Releasing the wrong item outside the DropArea invalidate the mechanism (until the next drop).

代码如下:

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"
    }
}

这篇关于拒绝拖入 DropArea 的外部文件而不破坏 DropArea的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆