在不破坏 DropArea 的情况下拒绝拖放到 DropArea 中的外部文件
Posted
技术标签:
【中文标题】在不破坏 DropArea 的情况下拒绝拖放到 DropArea 中的外部文件【英文标题】:Reject external files dragged in a DropArea without breaking the DropArea 【发布时间】:2014-04-01 13:23:12 【问题描述】:在我的应用程序中,我正在显示音频文件列表,用户可以拖动外部文件将其添加到列表中。如果我的应用程序不支持列表中的文件,我希望能够拒绝拖动。
问题是,当我在 onEntered
或 DropArea
中调用 drag.accepted = false;
时,它对任何其他事件都完全没有响应。
这里是一些显示问题的示例代码。如果您在窗口中拖动 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 上获得的视觉反馈。
【问题讨论】:
您找到解决方案了吗?我现在正在处理完全相同的问题。 不,我最终接受了文件,然后只过滤了我自己想要的文件 这已在 Qt 5.6 中修复。 【参考方案1】:很久以来一直是known bug。已经提交了一个补丁,经过几个月的停滞,现在是merged into 5.6 branch。
任何想要使用此功能的人都必须升级到 Qt 5.6 或可以将可用的补丁集成到他/她的 Qt 版本中。
QQuickDropAreaPrivate
,包含在DropArea
中,当dragEnterEvent
出现时,将containsDrag
标志更新为true
,发出entered
信号。当dragLeaveEvent
发生时,它将containsDrag
更新为false
,发出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"
【讨论】:
【参考方案2】:你从来没有把accepteed = true
将valid设置为valid后只需添加drag.accepted = true
for(var i = 0; i < drag.urls.length; i++)
if(validateFileExtension(drag.urls[i]))
validFile = true;
drag.accepted = true;
break;
【讨论】:
已经尝试过了,它并没有改变任何东西。接受拖动的行为与什么都不做一样以上是关于在不破坏 DropArea 的情况下拒绝拖放到 DropArea 中的外部文件的主要内容,如果未能解决你的问题,请参考以下文章