RCP:拖拽功能的实现 Drag and Drop
SWT中的拖拽是使用的org.eclipse.swt.dnd。
有三个需要密切注意的类:
1、DragSource
2、DropTarget
3、Transfer
DragSource封装了需要被拖拽的Control
DropTarget封装了拖拽的目标Control,即是拖拽终点的容器
Transfer是一个转换器,用于Java表示和平台指定的数据之间的相互转换
根据以上,我们可以揣测:
1、只有被DragSource封装了的Control对象才能被拖拽
2、只有被DropTarget封装了的Control对象才能被放置拖拽对象
3、同一次操作中,DragSource和DropTarget所定义的Transfer必须匹配
了解了这些基础,我们来看一个例子(该示例来自网络):
package z_test_project; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.*; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; public class DNDExample { public static void main(String[] args) { Shell shell = new Shell(); shell.setBackground(new Color(null, 200, 200, 200)); shell.setLayout(new GridLayout(2, false)); // Create the tree and some tree items final Tree tree = new Tree(shell, SWT.NONE); TreeItem item1 = new TreeItem(tree, SWT.NONE); item1.setText("Item 1"); TreeItem item2 = new TreeItem(tree, SWT.NONE); item2.setText("Item 2"); // Create the drag source on the tree DragSource ds = new DragSource(tree, DND.DROP_MOVE); ds.setTransfer(new Transfer[] {TextTransfer.getInstance()}); ds.addDragListener(new DragSourceAdapter() { public void dragSetData(DragSourceEvent event) { // Set the data to be the first selected item's text event.data = tree.getSelection()[0].getText(); } }); // Create the text field final Text text = new Text(shell, SWT.NONE); // Create the drop target on the text field DropTarget dt = new DropTarget(text, DND.DROP_MOVE); dt.setTransfer(new Transfer[] {TextTransfer.getInstance()}); dt.addDropListener(new DropTargetAdapter() { public void drop(DropTargetEvent event) { // Set the text field's text to the text being dropped text.setText((String)event.data); } }); shell.pack(); shell.open(); Display display = Display.getDefault(); while (!shell.isDisposed()) if (!display.readAndDispatch()) display.sleep(); display.dispose(); } }
效果如图:
这只是实现了简单的控件和控件之间的拖拽。
现在我们来实现两个功能,从导航器或者操作系统里向编辑器中拖拽。
首先是导航器,大部分导航器使用了TreeViewer展示,org.eclipse.jface.viewers.StructuredViewer#addDragSupport方法为TreeViewer的Control添加了DragSource
即是创建DragSource的步骤已经预先完成了。
题外:使用CNF生成的导航器必然会用到扩展点org.eclipse.ui.navigator.navigatorContent
其下有元素navigatorContent,其下又有元素dropAssitant
从命名可以看出,它指定的类是用来封装DropTarget和DropListener的
其内部实现有兴趣的自己阅读源码。
这部分是为了让导航器的内容可以在导航器内部拖拽。
然后我们写一个编辑器,使用一个Text填充,Text部分源码如下:
final Text text = new Text(composite, SWT.MULTI | SWT.BORDER); text.setText("测试页1"); DropTarget dropTarget = new DropTarget(text, DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_TARGET_MOVE); dropTarget.setTransfer(new Transfer[] { LocalSelectionTransfer.getTransfer(), FileTransfer.getInstance() }); dropTarget.addDropListener(new DropTargetAdapter() { @Override public void drop(DropTargetEvent event) { text.setText(event.data == null ? null : event.data.toString()); } });
注意红字部分,第一个LocalSelectionTransfer是为了让DropTarget能匹配导航器拖拽的部分内容,第二个FileTransfer是为了让其能匹配操作系统拖拽的文件。
以上即实现了拖拽功能。
这里提出一个问题,Text是如何识别到底一个拖拽进来的元素是否能够放置的呢?
这里,就需要看Transfer#validate的实现了。
如果被拖拽的元素能通过DropTarget所指定的任何一个Transfer的validate,就会被该Transfer所处理,然后转化为Java对象,应用到DropTarget封装的Control上去。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)