我正在为JList组件提供拖放支持,并且我希望能够支持从文件浏览器中拖动的文件。但是我只想允许文件而不是文件夹被拖入。因此,我试图像这样在我的TransferHandler中检查它:

@Override
public boolean canImport(TransferSupport support) {

    if (support.getComponent().equals(this.resourceFileList)) {

        if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            return false;
        } else {

            try {

                // get file list
                Transferable transferable = support.getTransferable();
                Object transferData = transferable.getTransferData(DataFlavor.javaFileListFlavor);

                // check for folders
                boolean containsFiles = false;
                List files = (List) transferData;
                for (int i = 0; i < files.size(); i++) {
                    File file = (File) files.get(i);
                    if (!file.isDirectory()) {
                        containsFiles = true;
                    }
                }

                // return file indicator
                return containsFiles;

            } catch (IOException | UnsupportedFlavorException e) {
                System.out.println("Unable to check for folders due to the following exception:\n" + e);
                return false;
            }
        }
    } else {
        return false;
    }
}


不幸的是,transferData在这里似乎为空。但是,不是在调用TransferHandler的importData方法时。如果这是某种错误或期望的行为,是否有人有任何线索?

我使用的是Mac(OSX 10.8),如果它有所作为,而Java版本是1.7.0_21。

提前致谢!

编辑:

这是供任何人测试的简短SSCCE。只需将文件拖到列表中,然后查看控制台即可。

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;

import java.io.File;
import java.io.IOException;

import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;

public class DNDIssue extends TransferHandler {

    @Override
    public boolean canImport(TransferSupport support) {

        if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {

            try {

                Transferable transferable = support.getTransferable();
                Object transferData = transferable.getTransferData(DataFlavor.javaFileListFlavor); // <-- this returns null
                System.out.println(transferData); // null

            } catch (IOException | UnsupportedFlavorException e) {
                System.out.println("Unable to check for folders due to the following exception:\n" + e);
            } finally {
                return false;
            }
        } else {
            return false;
        }
    }

    public static void main(String[] args) {

        // create window
        JFrame window = new JFrame("DNDIssue");
        window.setSize(640, 480);
        window.setLocation(100, 100);

        // create list with model and set transfer handler
        JList<File> list = new JList<File>(new DefaultListModel<File>());
        list.setTransferHandler(new DNDIssue());

        // add enclosing scroll pane and display window
        window.getContentPane().add(new JScrollPane(list));
        window.setVisible(true);
    }
}

最佳答案

您的SSCCE在Windows 7 64bit上使用JDK 1.7.0_21对我来说工作正常。
您可以尝试以下代码吗?

Transferable transferable = support.getTransferable();

System.out.println("----");
String mt = DataFlavor.javaFileListFlavor.getMimeType();
for(DataFlavor df: transferable.getTransferDataFlavors()) {
  System.out.println(df.getMimeType());
  System.out.println("  "+df.getMimeType().equals(mt));
}

SSCCE 1.0:删除
SSCCE 1.1:覆盖TransferHandler#importData(...)版本


InvalidDnDOperationException:没有下降电流

java.awt.dnd.InvalidDnDOperationException: No drop current
    at sun.awt.dnd.SunDropTargetContextPeer.getTransferData(SunDropTargetContextPeer.java:245)
    at sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:73)
    at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:376)
    at FileTransferHandler.canImport(DNDIssueTest.java:64)

该问题可能与Bug ID 6759788 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6759788有关


通过:http://www.coderanch.com/t/466319/GUI/java/Drag-Drop


SSCCE 1.2:忽略InvalidDnDOperationException




import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.*;
import java.util.List;
import javax.swing.*;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;

public class DNDIssueTest {
  public JComponent makeUI() {
    // create list with model and set transfer handler
    JList<File> list = new JList<File>(new DefaultListModel<File>());
    list.setDropMode(DropMode.INSERT);
    list.setTransferHandler(new FileTransferHandler());
    return new JScrollPane(list);
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new DNDIssueTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class FileTransferHandler extends TransferHandler {
  private static final boolean DEBUG = true;
  @SuppressWarnings("unchecked")
  @Override public boolean importData(TransferSupport support) {
    try {
      List files = (List)support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
      System.out.println("importData");
      if(!hasDirectory(files) && canImport(support)) {
        JList list = (JList)support.getComponent();
        DefaultListModel model = (DefaultListModel)list.getModel();
        for(Object o: files) {
          model.addElement(o);
        }
        return true;
      }
    } catch(Exception ex) {
      ex.printStackTrace();
    }
    return false;
  }
  private boolean hasDirectory(List list) {
    System.out.println("hasDirectory check");
    for (Object o: list) {
      if(o instanceof File) {
        File file = (File) o;
        if (file.isDirectory()) {
          return true;
        }
      }
    }
    return false;
  }
  @Override public boolean canImport(TransferSupport support) {
    if(!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      return false;
    }
    if(!DEBUG) return true;

    Transferable transferable = support.getTransferable();
    try {
      Object transferData = transferable.getTransferData(DataFlavor.javaFileListFlavor);
      //System.out.println(transferData); // null
      System.out.println("canImport");
      return !hasDirectory((List)transferData);
    } catch (Exception e) {
      //e.printStackTrace();
      System.out.println("*** Ignore InvalidDnDOperationException ***");
      return true;
    }
  }
}



SSCCE 2.0:DropTargetListener版本




import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.io.*;
import java.util.List;
import javax.swing.*;

public class DNDIssueTest2 {
  public JComponent makeUI() {
    final DefaultListModel<File> model = new DefaultListModel<>();
    JList<File> list = new JList<File>(model);
    DropTargetListener dtl = new DropTargetAdapter() {
      @Override public void dragOver(DropTargetDragEvent dtde) {
        if(dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
          Transferable transferable = dtde.getTransferable();
          Object transferData = null;
          try {
            transferData = transferable.getTransferData(DataFlavor.javaFileListFlavor);
          } catch(Exception ex) {
            dtde.rejectDrag();
            return;
          }
          List<File> files = (List<File>)transferData;
          for (int i = 0; i < files.size(); i++) {
            File file = (File) files.get(i);
            if (file.isDirectory()) {
              dtde.rejectDrag();
              return;
            }
          }
          dtde.acceptDrag(DnDConstants.ACTION_COPY);
          return;
        }
        dtde.rejectDrag();
      }
      @Override public void drop(DropTargetDropEvent dtde) {
        try {
          if(dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            dtde.acceptDrop(DnDConstants.ACTION_COPY);
            Transferable transferable = dtde.getTransferable();
            List list = (List)transferable.getTransferData(DataFlavor.javaFileListFlavor);
            for(Object o: list) {
              if(o instanceof File) {
                File file = (File) o;
                model.addElement(file);
              }
            }
            dtde.dropComplete(true);
            return;
          }
        } catch(UnsupportedFlavorException ufe) {
          ufe.printStackTrace();
        } catch(IOException ioe) {
          ioe.printStackTrace();
        }
        dtde.rejectDrop();
      }
    };
    new DropTarget(list, DnDConstants.ACTION_COPY, dtl, true);
    return new JScrollPane(list);
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new DNDIssueTest2().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

关于java - 当调用TransferHandler canImport方法时,默认情况下是否从jvm外部传输可转移项的传输数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16592166/

10-10 05:57