1. 拖放操作的介质:
1) 拖放操作的目的:就是为了程序之间的数据交流,更重要的是程序和操作系统之间的交流,因此如果拖放操作只在Java程序之间进行基本上是毫无意义的,拖放操作的初衷就是为了让操作系统上各程序之间可以进行交流,其中最最主要的形式就是程序和操作系统之间的数据交流;
2) 之前的示例就是拿操作系统的资源管理器作为拖放源,从那里拖动文件到Java程序中,很显然操作系统是拖放操作的一个必要介质,原因很简单,几乎90%以上的拖放操作都是要经过操作系统的(特别是操作系统上的文件系统);
3) 因此拖放是操作系统的原生功能,AWT的拖放操作底层完全依赖所在的操作系统,只不过在拖放目标上被隐藏的很好,几乎看不到有操作系统参与的地方,但不过在拖放源的处理上就明显带有操作系统的色彩了;
4) 拖放源上是如何体现出操作系统色彩呢?因为拖放源是产生待传输数据的地方,而数据必须是通过操作系统传输给另一个程序的,因此必须通过操作系统的系统调用获取和平台适配的拖放源;
2. 创建拖放源:
1) 前面说过了拖放源必须与操作系统适配,因此创建拖放源需要调用DragSource的方法getDefaultDragSource:public static DragSource getDefaultDragSource();
!!该方法将获取默认的拖放源,即与当前平台适配的拖放源;
2) 有了拖放源对象之后就必须指定一个GUI组件作为拖放源,并识别发生在拖放源上的拖放动作,因此这里就要创建拖放源的识别器:
i. 调用DragSource对象的createDefaultDragGestureRecognizer方法,在指定一个组件为拖放源的同时还规定了该拖放源可以接受的动作以及监听拖放动作的监听器;
ii. 原型:DragGestureRecognizer createDefaultDragGestureRecognizer(Component c, int actions, DragGestureListener dgl);
a. c就是和拖放源对象绑定起来的拖放源组件;
b. actions仍然是DnDConstants定义的动作;
c. dgl是用来监听并响应拖放事件的监听器;
3) DragGestureListener:
i. 拖放动作监听器,它仅仅是一个笼统的监听器,里面只有一个接口方法dragGestureRecognized,仅仅表示拖放动作发生了;
ii. 方法原型:void dragGestureRecognized(DragGestureEvent dge);
iii. 必须在该方法中编写从拖放源产生传输数据的代码;
iv. 同样,拖放操作传输的数据也必须支持Transferable接口,因此要注意产生的数据必须是实现Transferable接口的;
v. 该方法的最后一步就是调用dge的startDrag方法将数据传送出去,调用该方法后就什么都不用管了,传到哪儿如何接受是拖放目标的事情了;
4) startDrag方法:
i. public void DragGestureEvent.startDrag(Cursor dragCursor, Transferable transferable);
a. dragCursor指定了拖动时的光标,有些程序在拖动时的光标的图形和普通的光标图形不一样,比如平时是一个箭头,而拖动时变成了一个手掌;
b. 如果不想自己制作光标的图形则可以使用系统预定义的光标图像,调用Cursor的getPredefinedCursor方法即可获取:public static Cursor getPredefinedCursor(int type); // 即获取系统预定义的光标
c. type是Cursor中定义的静态常量,常用的有:
DEFAULT_CURSOR:默认的箭头贯标
CROSSHAIR_CURSOR:十字光标
TEXT_CURSOR:文本编辑光标
HAND_CURSOR:手掌光标
d. transferable就是要传输的数据,该方法调用后数据就会被传到拖放源上;
ii. 之前讲过了,在DragGestureListener中只能单纯的监控拖动是否发生了,但不能监控具体发生了什么拖动动作,那么现在在startDrag的重载版本中就可以监控特定的拖动动作了: public void startDrag(Cursor dragCursor, Transferable transferable, DragSourceListener dsl);
!!!最后一个参数dsl就是拖动源监听器,和DragDropListener相对应,里面有5个处理器来处理具体的拖动动作,每个处理器的事件参数自查;
a. dragDropEnd:拖放完成时触发
b. dragEnter:光标进入拖放源时触发
c. dragExit:光标离开拖放源时触发
d. dragOver:光标在拖放源上移动时触发
e. dragActionChanged:在拖放源上改变了组合键时触发
3. 拖放源示例:
public class AwtTest {
public void init() {
JFrame jf = new JFrame("Drag Source Test");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel src = new JLabel("Drag this line to other program!\nThank you!\n");
jf.add(src);
DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
src, DnDConstants.ACTION_COPY_OR_MOVE, e -> { // 必须要生成Transferable数据
Transferable data = new StringSelection(src.getText());
e.startDrag(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR), data);
}); // 拖动时采用手掌形光标
jf.pack();
jf.setVisible(true);
}
public static void main(String[] args)
{
new AwtTest().init();
}
}
!这里可以将标签中的文本直接拖放到其它程序中(比如记事本中);