我正在尝试在我们的产品中加入拖放功能。我创建了一个新的自定义视图,它具有树结构,并且有兴趣将该树中的内容放到应用程序本身的现有树结构中。
我使用了产品所期望的相同自定义传输类型。但是,在调试时我发现DragSourceEvent
的数据或数据类型都没有设置。
两者都是null
值。此外,我的dragSetData
也没有被调用。
请你提供一些建议......
答案 0 :(得分:0)
事件的数据仅在丢弃获取数据后设置。这应该会自动发生,但最初也不适用于我。
经过一番研究后,我想出了一个解决方法,虽然我不确定这是否是框架的意图。我在我的解决方案中扩展了 org.eclipse.jface.viewers.ViewerDropAdapter ,但它也适用于扩展 org.eclipse.swt.dnd.DropTargetAdapter :
public class MyViewerDropAdapter extends ViewerDropAdapter {
// implement the abstract methods
// the next two methods are the important part:
// override the non-abstract methods dragEnter and dragOperationChanged
// if your user just moves the mouse without pressing a key, event.detail
// equals DND.DROP_DEFAULT. In this case you have to change detail to
// your default operation (in this case DROP_COPY)
@Override
public void dragEnter(DropTargetEvent event) {
if (event.detail == DND.DROP_DEFAULT) {
if ((event.operations & DND.DROP_COPY) != 0) {
event.detail = DND.DROP_COPY;
} else {
event.detail = DND.DROP_NONE;
}
}
super.dragEnter(event);
}
// the same for this method. It will be called, when the user
// presses the CTRL or SHIFT button (on windows) while dragging.
// We need it here to set the DROP_DEFAULT back to DROP_COPY.
// Otherwise your default will go back to DROP_NONE after the user
// released the key.
@Override
public void dragOperationChanged(DropTargetEvent event) {
if (event.detail == DND.DROP_DEFAULT) {
if ((event.operations & DND.DROP_COPY) != 0) {
event.detail = DND.DROP_COPY;
} else {
event.detail = DND.DROP_NONE;
}
}
}
}
然后将删除支持添加到树查看器时,请确保除了其他操作之外还设置DND.DROP_DEFAULT操作(API doc afaik中未提及):
myTreeViewer.addDropSupport(DND.DROP_COPY | DND.DROP_DEFAULT,
new Transfer[] { myByteTransfer.getInstance() },
new MyViewerDropAdapter(myTreeViewer));
执行此操作后,调用了dragSetData,一切都按预期工作。
控制台输出显示某些事件的顺序:
Start Drag
dragEnter called
dragSetData called
drop called
performDrop called
Finshed Drag
答案 1 :(得分:0)
<强>解决方案强>
如果我们希望用户在不使用元键的情况下拖动条目,我们应该始终在拖放结束时允许 system-default 拖动操作。在Windows上,这恰好是DND.DRAG_MOVE
操作(我相信其他平台也是如此)。
source.addDragSupport(DND.DROP_MOVE, new Transfer[] { DragSelectionListener.getTransfer() }, new DragSelectionListener(viewer));
target.addDropSupport(DND.DROP_MOVE, new Transfer[]{ DropListListener.getTransfer() }, new DropListListener(viewer));
<强>解释强>
三组操作应相交:
然后,drop target将验证收到的丢弃,并且将请求拖动源数据。
<强>研究强>
元键的处理在org.eclipse.swt.dnd.DropTarget.setEventData()
行
operations[0] = osToOp(operations[0]) & style;
if (operations[0] == DND.DROP_NONE) return false;
将来自droptarget的样式与来自系统删除操作的值相交,它基于dragsource但被剥离DND.DRAG_DEFAULT
。如果这两个不相交,则操作中止。
再将此设置与按下的元键计算出的设置进行比较。操作可以再次中止。
if ((operation & operations[0]) == 0) operation = DND.DROP_NONE;
可以控制此行为从DND.DROP_DEFAULT
传递到addDropSupport()
,但这更糟糕,因为用户选择的操作将与DND.DROP_MOVE
进行比较,如果不是,则会先过滤掉用作addDropSupport()
的参数。
我认为DND.DROP_DEFAULT
处理已经破坏,不应该依赖。如果第一个条件有效地阻止了它的使用。