Java 无法执行拖放操作;未调用dragSetData

Java 无法执行拖放操作;未调用dragSetData,java,drag-and-drop,tree,swt,Java,Drag And Drop,Tree,Swt,我正在尝试将拖放功能与我们的产品结合起来。我已经创建了一个新的自定义视图,它有一个树状结构,我想将内容从这个树状结构中删除到应用程序本身中已经存在的树状结构中 我使用了与产品预期相同的自定义传输类型。但是,在调试时,我发现DragSourceEvent的数据或数据类型都没有设置。 两者都是null值。此外,我的dragSetData也没有被调用 请您提供一些建议……只有在drop获得数据后,才会设置事件的数据。这应该是自动发生的,但一开始对我来说也不起作用 经过一些研究,我想出了一个解决办法,尽

我正在尝试将拖放功能与我们的产品结合起来。我已经创建了一个新的自定义视图,它有一个树状结构,我想将内容从这个树状结构中删除到应用程序本身中已经存在的树状结构中

我使用了与产品预期相同的自定义传输类型。但是,在调试时,我发现
DragSourceEvent
的数据或数据类型都没有设置。 两者都是
null
值。此外,我的
dragSetData
也没有被调用


请您提供一些建议……

只有在drop获得数据后,才会设置事件的数据。这应该是自动发生的,但一开始对我来说也不起作用

经过一些研究,我想出了一个解决办法,尽管我不确定这是否是框架的意图。我在解决方案中扩展了org.eclipse.jface.viewers.ViewerDropAdapter,但它也应该与扩展org.eclipse.swt.dnd.DropTargetAdapter一起工作:

然后,当您将drop支持添加到树查看器中时,请确保除了其他操作(API文档afaik中未提及)之外,还设置了DND.drop_默认操作:

在我这样做之后,dragSetData被调用,一切都按预期进行

控制台输出显示一些事件的顺序:

Start Drag
dragEnter called
dragSetData called
drop called
performDrop called
Finshed Drag

解决方案

如果我们希望用户在不使用元键的情况下拖动条目,我们应该始终允许系统默认值在拖放端进行拖动操作。在Windows上,这恰好是一个
DND.DRAG\u MOVE
操作(我相信其他平台也是如此)

解释

三组操作应相交:

  • 拖动源允许的操作(使用StructuredViewer.addDragSupport()设置)
  • 拖动目标支持的操作(使用StructuredViewer.addDropSupport()设置)
  • 用户选择的操作(取决于跌落时按下的元键)
只有这样,drop target才会验证接收到的drop,并请求drag source获取数据

调查

元键的处理在
org.eclipse.swt.dnd.DropTarget.setEventData()行中完成

operations[0] = osToOp(operations[0]) & style;
if (operations[0] == DND.DROP_NONE) return false;
droptarget中的intersects样式与来自系统拖放操作的值基于dragsource,但去掉了DND。DRAG_默认值
。如果这两个不相交,操作将中止

再往下看,这组数据将与按元键计算的数据进行比较。操作可能会再次中止

if ((operation & operations[0]) == 0) operation = DND.DROP_NONE;
通过将
DND.DROP\u DEFAULT
传递到
addDropSupport()
,可以控制此行为,但更糟糕的是,用户选择的操作将与
DND.DROP\u MOVE
进行比较,如果不将其用作
addDropSupport()
的参数,则会在前面过滤掉

我认为
DND.DROP\u默认
处理已被破坏,不应依赖。它的使用,如果有效地防止了第一个条件

source.addDragSupport(DND.DROP_MOVE, new Transfer[] { DragSelectionListener.getTransfer() }, new DragSelectionListener(viewer));
target.addDropSupport(DND.DROP_MOVE, new Transfer[]{ DropListListener.getTransfer() }, new DropListListener(viewer));
operations[0] = osToOp(operations[0]) & style;
if (operations[0] == DND.DROP_NONE) return false;
if ((operation & operations[0]) == 0) operation = DND.DROP_NONE;