blog211119. SWT之DnD

DnD过程

Drag and Drop操作用可视化的完成两个widget之间data的传递. 发起方称作drag source, 接收方称作drop target.
一个典型的DnD操作包括,

  1. 在drag source widget上点压鼠标左键,
  2. 拖拽鼠标, 即不放开鼠标键的同时, 向drag target移动,
  3. 移动到drop target widget上释放鼠标键.

1和2是drag, 3是drop.

整个过程中, 可以同时加按键盘ctrl或者shift键决定拖拽要执行的操作种类, 包括

  • DND.DROP_COPY, 从source到target复制, cursor提示一个’+’, 加按ctrl.
  • DND.DROP_MOVE, 从source到target迁移. 加按shift.
  • DND.DROP_LINK, 从source到target建立link, cursor提示一个跳转符号.加按shift+ctrl
  • DND.DROP_DEFAULT, 默认的操作种类, 不加按键盘键情形下. 通常由系统决定采用何种操作, 一般是DROP_MOVE.
  • DND.DROP_NONE, 提示当前位置下的widget不接受drop, cursor提示为一个禁止符号.

拖拽过程中, 主要通过以下视觉变化提示DnD操作的状态,

  • cursor图像
  • source widget的外观
  • target widget的外观

SWT中用DragSource和DropTarget负责实现DnD功能的实现.
DragSource的DragSourceListener完成source侧的事件处理, 而DropTarget的DropTargetListener负责target侧的事件处理.

DragSourceListener

public interface DragSourceListener extends SWTEventListener 
{
	public void dragStart(DragSourceEvent event);
	public void dragSetData(DragSourceEvent event);
	public void dragFinished(DragSourceEvent event);
}

source的3个事件,

  • dragStart, 指示用户将发起一个DnD, 一般是用户按压鼠标并拖拽一小距离后触发. 若用户选择取消发起, 则设置 event.doit= false.
  • dragSetData, 指示用户提供data, 系统据此要求target判断是否允许该DnD, 以及drop时target使用该data.
  • dragFinished, 指示用户DnD结束. 当DnD操作失败时, 例如用户按esc取消或者在不接受DnD的target上drop, event.detail的值是DND.DROP_NONE.

source event sequence有以下几种情形,

  • dragStart
  • dragStart, dragSetData{0,n}, dragFinished

DropTargetListener

public interface DropTargetListener extends SWTEventListener {
	public void dragEnter(DropTargetEvent event);
	public void dragLeave(DropTargetEvent event);
	public void dragOperationChanged(DropTargetEvent event);
	public void dragOver(DropTargetEvent event);
	public void drop(DropTargetEvent event);
	public void dropAccept(DropTargetEvent event);
}

target的6个事件

  • dragEnter, 鼠标移入target时触发. 在此用户可以设置event.detail, 决定操作种类.
  • dragLeave, 鼠标移出target或者用户esc取消时触发. 通常用户应在此释放dragEnter中申请的资源.
  • dragOperationChanged, DnD操作种类变更时触发, 通常是用户改变键盘按键导致.
  • dragOver, 鼠标在target widget上hover时触发. 可以设置event.detail, event.currentType和event.feedback. 而feedback通常用于tree和table中的DnD.
  • dropAccept, 触发判断是否接受DnD并进入到下一步drop.
  • drop, 成功完成DnD时触发, 用户在此执行读取data和实质动作.

target event sequence有以下几种情形

  • dragEnter, dragLeave
  • dragEnter, (dragOver | dragOperationChanged){1,n}, dragLeave
  • dragEnter, (dragOver | dragOperationChanged){1,n}, dragLeave, dropAccept
  • dragEnter, (dragOver | dragOperationChanged){1,n}, dragLeave, dropAccept, drop

典型代码

代码出自eclipse的一篇DnD的介绍, DnD in SWT

import org.eclipse.swt.dnd.*;
 
// Enable a label as a Drag Source
final Label dragLabel = new Label(shell, SWT.BORDER);
dragLabel.setText("text to be transferred");
 
// Allow data to be copied or moved from the drag source
int operations = DND.DROP_MOVE | DND.DROP_COPY;
DragSource source = new DragSource(dragLabel, operations);
	 
// Provide data in Text format
Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
source.setTransfer(types);
 
source.addDragListener(new DragSourceListener() {
   public void dragStart(DragSourceEvent event) {
	  // Only start the drag if there is actually text in the
	  // label - this text will be what is dropped on the target.
	  if (dragLabel.getText().length() == 0) {
		  event.doit = false;
	  }
   }
   public void dragSetData(DragSourceEvent event) {
	 // Provide the data of the requested type.
	 if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
		  event.data = dragLabel.getText();
	 }
   }
   public void dragFinished(DragSourceEvent event) {
	 // If a move operation has been performed, remove the data
	 // from the source
	 if (event.detail == DND.DROP_MOVE)
		 dragLabel.setText("");
	 }
   }
});
import org.eclipse.swt.dnd.*;
 
// Enable a table as a Drop Target
final Table dropTable = new Table(shell, SWT.BORDER);
for (int i = 0; i < 10; i++) {
    TableItem item = new TableItem(dropTable, SWT.NONE);
    item.setText("item" + I);
}
 
// Allow data to be copied or moved to the drop target
operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;
DropTarget target = new DropTarget(dropTable, operations);
 
// Receive data in Text or File format
final TextTransfer textTransfer = TextTransfer.getInstance();
final FileTransfer fileTransfer = FileTransfer.getInstance();
types = new Transfer[] {fileTransfer, textTransfer};
target.setTransfer(types);
 
target.addDropListener(new DropTargetListener() {
  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;
		 }
	 }
	 // will accept text but prefer to have files dropped
	 for (int i = 0; i < event.dataTypes.length; i++) {
		 if (fileTransfer.isSupportedType(event.dataTypes[i])){
			 event.currentDataType = event.dataTypes[i];
			 // files should only be copied
			 if (event.detail != DND.DROP_COPY) {
				 event.detail = DND.DROP_NONE;
			 }
			 break;
		 }
	 }
   }
   public void dragOver(DropTargetEvent event) {
		event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_SCROLL;
		if (textTransfer.isSupportedType(event.currentDataType)) {
			// NOTE: on unsupported platforms this will return null
			Object o = textTransfer.nativeToJava(event.currentDataType);
			String t = (String)o;
			if (t != null) System.out.println(t);
		}
	}
	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;
			}
		}
		// allow text to be moved but files should only be copied
		if (fileTransfer.isSupportedType(event.currentDataType)){
			if (event.detail != DND.DROP_COPY) {
				event.detail = DND.DROP_NONE;
			}
		}
	}
	public void dragLeave(DropTargetEvent event) {
	}
	public void dropAccept(DropTargetEvent event) {
	}
	public void drop(DropTargetEvent event) {
		if (textTransfer.isSupportedType(event.currentDataType)) {
			String text = (String)event.data;
			TableItem item = new TableItem(dropTable, SWT.NONE);
			item.setText(text);
		}
		if (fileTransfer.isSupportedType(event.currentDataType)){
			String[] files = (String[])event.data;
			for (int i = 0; i < files.length; i++) {
				TableItem item = new TableItem(dropTable, SWT.NONE);
				item.setText(files[i]);
			}
		}
	}
});

驽马一架 2021/11/19

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值