【问题标题】:Drag and Drop Files - TransferHandler vs. DropTarget vs. FileDrop?拖放文件 - TransferHandler vs. DropTarget vs. FileDrop?
【发布时间】:2021-05-25 04:14:33
【问题描述】:

所以,在How can I use Drag-and-Drop in Swing to get file path?中,建议了几种不同的解决方案:一种指向TransferHandler tutorial(实际上并没有解释如何拖放文件,只解释了拖动JComponents,然后给出了一个带有多个移动的demo部分,文件没有解释),一个使用DropTargetDropTargetDropEvent,一个使用名为FileDrop的外部库。第四个答案(谢天谢地)实际上解释了TransferHandler 是什么以及如何为文件实现它,但我的问题是:

哪种方法最适合使用?

如果有原生支持我不知道使用外部库,但我不明白的是DropTarget

我以前只看到DropTarget 用在用 Java 7 和更早版本编写的程序中,所以我认为它已被 TransferHandler 废弃,但链接问题中的解决方案说它应该用于 Java 7 或以后。我很困惑。

感谢您的宝贵时间,我期待您的回复!

【问题讨论】:

    标签: java swing file drag-and-drop


    【解决方案1】:

    恕我直言,通常没有最好的拖放方法。对于简单的文件拖放(例如文件资源管理器中的文件),我会使用DropTargetListenerTransferHandle 很可能用于组件或应用程序之间的拖放。

    您需要DropTarget 来定义放置操作的类型(例如复制和/或移动)和DropTargetListener

    一个你可能知道的例子(有点乱): Drag&Drop Example on stackoverflow

    作为一个例子,我编写了一个面板类,通过DropTargetListener 实现拖放。覆盖importFiles 的此类派生可以直接访问List<File>

    import java.awt.dnd.*;
    import java.awt.datatransfer.*;
    import java.io.File;
    import java.util.List;
    import java.util.ArrayList;
    import javax.swing.JPanel;
    
    @SuppressWarnings("serial")
    public class DropTargetPanel extends JPanel implements DropTargetListener {
        private static final String NL = "\\r?\\n";
        private static final List<DataFlavor> supportedFlavors = 
            new ArrayList<>( List.of(DataFlavor.javaFileListFlavor, DataFlavor.stringFlavor) );
    
        public DropTargetPanel() {
            super();
            new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
        }
        
        @Override
        public void dragEnter(DropTargetDragEvent dtde) {
            if(supportedFlavors.contains(dtde.getCurrentDataFlavors()[0])) {
                dtde.acceptDrag(DnDConstants.ACTION_COPY);
            } else {
                dtde.rejectDrag();
            }
        }
    
        @Override
        public void dragOver(DropTargetDragEvent dtde) {
            dragEnter(dtde);
        }
    
        @Override
        public void dropActionChanged(DropTargetDragEvent dtde) { /* */ }
    
        @Override
        public void dragExit(DropTargetEvent dte) { /* */ }
    
        @SuppressWarnings("unchecked")
        @Override
        public void drop(DropTargetDropEvent dtde) {
            // It looks like only the first flavor is guaranteed to work for me - so what
            DataFlavor df = dtde.getCurrentDataFlavors()[0];
            Transferable transferable = dtde.getTransferable();
            
            if(supportedFlavors.contains(df)) {
                dtde.acceptDrop(dtde.getDropAction());
                if(df.isFlavorJavaFileListType()) {
                    try { importFiles((List<File>)transferable.getTransferData(df)); }
                    catch (Exception e) { e.printStackTrace(); } 
                } else {
                    try { importFiles(getFiles(((String)transferable.getTransferData(df)).split(NL))); } 
                    catch (Exception e) { e.printStackTrace(); } 
                }                
                dtde.dropComplete(true);
            }
            else dtde.rejectDrop();
        }
    
        // Creates a List<File> from a String Array
        private List<File> getFiles(String[] files){
            List<File> result = new ArrayList<>();
            for(int i = 0; i < files.length; i++) result.add(new File(files[i]));
            return result;
        }
    
        // Override this to gain access for the list of files
        protected void importFiles(List<File> files) {
            //
        }
    }
    

    【讨论】:

    • 您好 QuinncyJones,您能解释一下您的答案吗?你的代码显示了什么?
    • 嗨,bsheps,我应该立即添加解释。感谢您的提示!
    猜你喜欢
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多