2013-04-16 82 views
2

我正在嘗試在我們的產品中加入拖放功能。我創建了一個新的自定義視圖,該視圖具有樹結構,並且有興趣將此樹中的內容放到應用程序本身內已有的樹結構中。無法實現拖放操作; dragSetData沒有被調用

我已經使用了產品所期望的相同的自定義傳輸類型。但是,在調試過程中,我發現DragSourceEvent的數據或數據類型都沒有設置。 兩者都是null的值。此外我的dragSetData也沒有被調用。

請求你給我提供一些建議....

回答

0

事件的數據的下降得到數據後,才設置。這應該會自動發生,但它起初也不適用於我。

經過一番研究,我想出了一個解決方法,雖然我不確定這是否是框架打算的。我伸出我的解決方案的org.eclipse.jface.viewers.ViewerDropAdapter,但它也應該延伸org.eclipse.swt.dnd.DropTargetAdapter工作:

public class MyViewerDropAdapter extends ViewerDropAdapter { 
    // implement the abstract methods 

    // the next two methods are the important part: 
    // override the non-abstract methods dragEnter and dragOperationChanged 
    // if your user just moves the mouse without pressing a key, event.detail 
    // equals DND.DROP_DEFAULT. In this case you have to change detail to 
    // your default operation (in this case DROP_COPY) 
    @Override 
    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; 
     } 
     } 
     super.dragEnter(event); 
    } 

    // the same for this method. It will be called, when the user 
    // presses the CTRL or SHIFT button (on windows) while dragging. 
    // We need it here to set the DROP_DEFAULT back to DROP_COPY. 
    // Otherwise your default will go back to DROP_NONE after the user 
    // released the key. 
    @Override 
    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; 
     } 
     } 
    } 
} 

當你再放入滴你的樹查看器的支持,一定要設置除其他人(在API文檔沒有提及據我所知)的DND.DROP_DEFAULT操作:

myTreeViewer.addDropSupport(DND.DROP_COPY | DND.DROP_DEFAULT, 
      new Transfer[] { myByteTransfer.getInstance() }, 
      new MyViewerDropAdapter(myTreeViewer)); 

我這樣做後,dragSetData接到電話和一切工作按預期。

控制檯輸出顯示你對一些事件的順序:

Start Drag 
dragEnter called 
dragSetData called 
drop called 
performDrop called 
Finshed Drag 
0

解決方案

如果我們想爲用戶拖動項不使用Meta鍵我們應該總是允許系統默認在拖放結束時拖動操作。在Windows上,這恰好是DND.DRAG_MOVE操作(我相信其他平臺的情況也是如此)。

source.addDragSupport(DND.DROP_MOVE, new Transfer[] { DragSelectionListener.getTransfer() }, new DragSelectionListener(viewer)); 
target.addDropSupport(DND.DROP_MOVE, new Transfer[]{ DropListListener.getTransfer() }, new DropListListener(viewer)); 

說明

三組操作的應相交:

  • 操作該拖動源允許(設置與StructuredViewer.addDragSupport())
  • 操作該拖動目標支持(使用StructuredViewer.addDropSupport()設置)
  • 用戶選擇的操作(取決於哪些元鍵被丟棄的時刻)

只有然後放下目標將驗證接收到的下降和拖動源將被請求的數據。

調查

元鍵的處理在org.eclipse.swt.dnd.DropTarget.setEventData()做行

operations[0] = osToOp(operations[0]) & style; 
if (operations[0] == DND.DROP_NONE) return false; 

相交從與來自系統拖放操作價值DropTarget的風格是基於DragSource上,但剝離的DND.DRAG_DEFAULT 。如果這兩個不相交,則操作被中止。

進一步下來這個集合與從元鍵被按下計算出來的集合進行比較。操作可能會再次中止。

if ((operation & operations[0]) == 0) operation = DND.DROP_NONE; 

此行爲可以被控制傳遞到DND.DROP_DEFAULTaddDropSupport(),但隨着用戶選擇的操作將被然後與DND.DROP_MOVE即更差,這將被過濾掉早期如果沒有用作的addDropSupport()參數。我認爲DND.DROP_DEFAULT處理是打破,不應該依靠。這是有用的,如果有效地防止了第一個條件。