6

在我的 Eclipse RCP 应用程序中,我有一个 TreeViewer,它是文件的放置目标,它在大多数情况下都能正常工作,但是当我尝试将存储在 CD ROM 上的文件从 Windows 资源管理器拖动到节点时,指示允许放置的图标不会't change and drop什么都不做。

由于人们似乎对我的问题感到困惑,这里有一个更详细的解释:

执行下面的代码(由 Baz 提供)时,我可以将文件拖放到文本框中,当我从机器上的大多数位置拖动文件时,窗口显示如下 ->

工作阻力

光标表示我可以放下,当我释放鼠标时,该drop(DropTargetEvent event)方法被调用。

现在,当我做同样的事情,但从资源管理器中获取一个位于我的光驱 DVD 上的文件时,它看起来像这样:

在此处输入图像描述

表示不允许放置,并且当我释放鼠标时,drop(DropTargetEvent event)不会调用该方法。

还值得注意的是,我可以将相同的 DVD 文件放入 Eclipse 导航器中的文件夹中,这表明这不是特定于机器的问题,Eclipse 树中必须有一些不同的东西允许它,但我可以'没看到。

package widgets;

import java.util.Arrays;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.PluginTransfer;

public class SourceTest {
    public static void main(String[] args) {
        final Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(1,false));

        final Text text = new Text(shell, SWT.BORDER);
        text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));

        DropTarget dt = new DropTarget(text, DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK);
        dt.setTransfer(new Transfer[] { FileTransfer.getInstance(), PluginTransfer.getInstance() });
        dt.addDropListener(new DropTargetAdapter() {
            public void drop(DropTargetEvent event) {
                String fileList[] = null;
                FileTransfer ft = FileTransfer.getInstance();
                if (ft.isSupportedType(event.currentDataType)) {
                    fileList = (String[]) event.data;
                }
                System.out.println(Arrays.toString(fileList));
            }
        });

        shell.setSize(300, 100);
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }

}
4

3 回答 3

4

当来自 CDROM 设备时,似乎并非所有可能的 DND 操作都受支持。因此,您需要在 上实现更多方法DropTargetAdapter,以便在进行中修改 Drop 操作,以缩小实际执行的操作范围,以便操作系统不会阻止 drop。

我举了你的例子,只是对DropTargetAdapter

    @Override
    public void dropAccept( DropTargetEvent event )
    {
        Object object = FileTransfer.getInstance().nativeToJava( event.currentDataType );
        if( object instanceof String[] )
        {
            String[] strs = (String[]) object;
            System.out.println("dropAccept " + strs[0]);
            event.detail = DND.DROP_COPY;
        }
        event.detail = DND.DROP_COPY;
    }
    @Override
    public void dragEnter( DropTargetEvent event )
    {
        event.detail = DND.DROP_COPY;
    }
于 2012-10-29T13:19:39.510 回答
1

我认为更新您的问题澄清了问题所在。

您的放置目标用作DND_MOVE标志。由于我们无法删除 DVD 等只读媒体中的文件,

发送者(在本例中为 OS 的外壳)将拒绝 DND 通信,无论接收者的决定是否是。

您的屏幕截图显示移动DND 反馈而不是复制

dropAccept()给您最后一次修改通信请求的机会,请谨慎使用,因为每个传输类型可以存在多个放置目标侦听器。为了支持这种情况,TreeViewer 的 DND API 与 SWT 的 API 略有不同。

于 2012-10-30T11:36:06.933 回答
0

DND 并不像您认为的那样工作。

考虑从网上下载一些文件。当您验证下载时,没有实际的文件内容,但您拥有 Web 资源的唯一 URL

同样,当您验证 drop 操作时,您无法知道实际数据,因为在您接受 drop 操作之前没有建立连接。在验证阶段你唯一能知道的就是传输类型

所以你只能根据内容类型来验证drop,而不是“Actual Content”

典型的验证码是:

public boolean validateDrop(...){
    return FileTransfer.getInstance().isSupportedType(transferData);
}

接受“TransferData”后,传输将从连接中检索实际数据。

所以请记住,“TransferData”与实际数据不同。

以数组的FileTransfer形式检索文件,String其中包含每个文件的绝对路径,而不是 JavaFile对象。

PS:剪贴板的工作方式相同。

于 2012-10-29T02:35:59.273 回答