2

製品にドラッグ アンド ドロップ機能を組み込もうとしています。ツリー構造を持つ新しいカスタム ビューを作成しましたが、このツリーからコンテンツをアプリケーション自体内の既存のツリー構造にドロップすることに関心があります。

製品が期待するのと同じカスタム転送タイプを使用しました。しかし、デバッグ中にDragSourceEventのデータもデータ型も設定されていないことがわかりました。どちらもnull値です。さらに、私dragSetDataも呼び出されていません。

私にいくつかの提案を提供するように要求します....

4

2 に答える 2

0

解決

ユーザーがメタ キーを使用せずにエントリをドラッグできるようにする場合は、ドラッグ エンドとドロップ エンドの両方で常にシステム デフォルトのドラッグ操作を許可する必要があります。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));

説明

3 つの操作セットが交差する必要があります。

  • ソースをドラッグできる操作 (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. この 2 つが交差しない場合、操作は中止されます。

さらに、このセットは、押されたメタ キーから計算されたものと比較されます。操作が再度中止される可能性があります。

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

この動作は に渡しDND.DROP_DEFAULTて制御できますaddDropSupport()が、ユーザーが選択した操作が と比較されるため、さらに悪いことになりDND.DROP_MOVEますaddDropSupport()

DND.DROP_DEFAULT扱いが壊れていて頼りにならないと思います。最初の条件によって効果的に防止された場合に使用します。

于 2013-10-21T10:22:03.370 に答える
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;
       }
      }
   }
}

その後、ツリー ビューアーにドロップ サポートを追加するときは、他の操作に加えて DND.DROP_DEFAULT 操作を設定してください (API doc afaik には記載されていません)。

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
于 2013-06-20T07:55:15.373 に答える