Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么可以';从windows中的CD将文件拖放到Eclipse/SWT拖放目标上_Java_Windows_Eclipse_Drag And Drop_Swt - Fatal编程技术网

Java 为什么可以';从windows中的CD将文件拖放到Eclipse/SWT拖放目标上

Java 为什么可以';从windows中的CD将文件拖放到Eclipse/SWT拖放目标上,java,windows,eclipse,drag-and-drop,swt,Java,Windows,Eclipse,Drag And Drop,Swt,在我的EclipseRCP应用程序中,我有一个TreeViewer,它是文件的拖放目标,在大多数情况下都可以正常工作,但是当我尝试将存储在CD-ROM上的文件从windows资源管理器拖到节点时,指示允许拖放的图标不会改变,拖放也不会做任何事情 由于人们似乎对我的问题感到困惑,这里有一个更详细的解释: 当执行下面的代码(由Baz提供)时,我可以将文件拖放到文本框中,当我从机器上的大多数位置拖动文件时,窗口显示如下-> 光标指示我可以拖放,当我释放鼠标时,将调用drop(DropTargetEv

在我的EclipseRCP应用程序中,我有一个TreeViewer,它是文件的拖放目标,在大多数情况下都可以正常工作,但是当我尝试将存储在CD-ROM上的文件从windows资源管理器拖到节点时,指示允许拖放的图标不会改变,拖放也不会做任何事情

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

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

光标指示我可以拖放,当我释放鼠标时,将调用
drop(DropTargetEvent事件)
方法

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

指示不允许拖放,当我释放鼠标时,不会调用
drop(DropTargetEvent事件)
方法

还值得注意的是,我能够将相同的DVD文件放入eclipse navigator中的一个文件夹中,这表明这不是一个特定于机器的问题,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();
    }

}

DND的工作方式与您认为的不同

考虑从web下载一些文件。 当您验证下载时,没有实际的文件内容,但您只有web资源的URL

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

因此,您只能根据内容类型而不是“实际内容”验证删除

典型的验证代码为:

public boolean validateDrop(...){
    return FileTransfer.getInstance().isSupportedType(transferData);
}
接受“TransferData”后,传输将从连接中检索实际数据

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

FileTransfer
String
数组的形式检索文件,该数组包含每个文件的绝对路径,而不是Java
file
对象


注意:剪贴板的工作方式与此相同。

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

我以您为例,只是对
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;
    }

我想你的问题澄清了问题所在

您的投掷目标使用了
DND\u MOVE
作为标志。 由于我们无法删除只读介质(如DVD)中的文件

发送方(在本例中为操作系统外壳)将拒绝DND通信,无论接收方的决定是否正确

您的屏幕截图显示移动DND反馈未复制

dropAccept()
为您提供最后一次修改通信请求的机会,
请小心使用,因为每个传输类型都可能存在多个drop目标侦听器。为了支持这种情况,TreeViewer的DNDAPI与SWT的略有不同。

您是否检查了
validateDrop
方法中的
transferType
是否与从HDD拖放时的不同?它们是TransferData对象,在结构上似乎没有任何重大差异,但是,对于ROM文件,操作似乎总是16,而对于工作的文件,当通过节点时,操作更改为2,当不通过节点时,操作更改为16,这向我表明,对于正在拖动的对象,节点没有注册为可行的目标。奇怪的是,尽管validateDrop并不打算实际允许您执行它,但还是调用了validateDrop。基于名称
**validate**Drop()
,这是有意义的。我会研究一下。也许我会找到一个解决方案。名称让它听起来像是应该删除的,但是在这种情况下,即使它返回true,框架也不会尝试执行删除,因为它已经确定目标无效。谢谢你提前抽出时间,谢谢,我都知道。你认为这个问题的答案是什么?我自己投了反对票,这肯定是一条详细的信息,但不是答案,jeeyul认为我不懂如何使用拖放,只是希望文件自动移动。事实并非如此,这是一项很好的工作,我的好朋友。因此,基本上覆盖细节,使其始终显示为副本?这不会导致其他事件类型的奇怪行为吗?因此,您可以添加一些代码,以便在“修改”此事件时更具选择性。我将在我的答案中添加一些代码,显示如何“嗅探”将要删除的内容的位置,并确定何时修改和何时离开。谢谢,我将看看是否可以在eclipse树中找到相应的代码。