2

我正在研究对 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在这里似乎为空。然而,不是在调用 TransferHandlerimportData方法时。如果这是某种错误或期望的行为,有人知道吗?

如果它有所作为并且Java版本是1.7.0_21,我在Mac(OSX 10.8)上。

提前致谢!

编辑:

这是一个简短的 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);
    }
}
4

1 回答 1

2
  • 您的 SSCCE 在 Windows 7 64 位上使用 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)
      
    • 该问题可能与错误 ID 6759788 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6759788有关

  • 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);
  }
}
于 2013-05-17T10:27:14.890 回答