在我的应用程序中,我正在显示音频文件列表,用户可以拖动外部文件将其添加到列表中。如果我的应用程序不支持列表中的文件,我希望能够拒绝拖动。
问题是,当我在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上获得的视觉反馈。
答案 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
的过滤。不幸的是,这种方法似乎不适合所提出的用例。
相当部分的解决方法是使用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"
}
}
答案 1 :(得分:-1)
你永远不会被接受=真实
在将有效设置为有效
后添加drag.accepted = truefor(var i = 0; i < drag.urls.length; i++) {
if(validateFileExtension(drag.urls[i])) {
validFile = true;
drag.accepted = true;
break;
}
}