zoukankan      html  css  js  c++  java
  • 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上去。

  • 相关阅读:
    谈谈final, finally, finalize的区别。
    session是存储在什么地方,以什么形式存储的
    如果有几千个session,怎么提高效率
    堆和栈的区别?
    进程和线程的区别?
    Delphi中启动项管理 已安装程序卸载简单组件
    在使用TStringlist谨慎使用For循环
    Delphi 中窗体全屏组件
    TEdit扩展:做成多按钮的Edit,可用作浏览器地址栏
    Delphi 7中处理TEdit鼠标进入 离开事件
  • 原文地址:https://www.cnblogs.com/anrainie/p/3600739.html
Copyright © 2011-2022 走看看