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上去。

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM