您的位置:首页 > 运维架构

RCP:拖拽功能的实现 Drag and Drop

2014-03-14 15:46 711 查看
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上去。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: