拖放:将文件从组件拖放到资源管理器、查找器等的操作



我有一个JTree,我想从JTree导出一些文件到资源管理器。为了做到这一点,我使用了TransferHandler和香料:DataFlavor.javaFileListFlavor。这样,资源管理器可以导入拖动的文件。问题是我的文件在服务器上,当可转移对象在资源管理器上被丢弃时,我需要下载它们。

当文件被放到资源管理器上时,我如何启动我的下载方法?我怎样才能知道我删除的文件的目标文件夹?

示例:

import java.awt.BorderLayout;
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.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

public class JTreeDnDSample extends JFrame
{
    protected JTree _tree;
    private DefaultTreeModel treeModel;
    private DefaultMutableTreeNode rootNode;
    private JScrollPane border;
    public static void main(String[] args) 
    {
        new JTreeDnDSample().setVisible(true);
    }
    public JTreeDnDSample()
    {
        super("Dnd");
        initializeTree();
        this.setLayout(new BorderLayout());
        border = new JScrollPane(this._tree);
        border.setBorder(BorderFactory.createTitledBorder("Tree"));
        this.add(border, BorderLayout.CENTER);
        this.setSize(400, 800);
    }
    protected void initializeTree()
    {
        this.rootNode = new DefaultMutableTreeNode("Root folder");
        this.treeModel = new DefaultTreeModel(rootNode);
        _tree = new JTree(treeModel);

        _tree.setName("TREE");
        _tree.setDragEnabled(true);  
        _tree.setDropMode(DropMode.ON_OR_INSERT);  
        _tree.setTransferHandler(new TreeTransferHandler());  
        _tree.setShowsRootHandles(true);
        _tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);    
        _tree.setRowHeight(26);
        //tree creation
        DefaultMutableTreeNode folder = new DefaultMutableTreeNode("folder1");
        DefaultMutableTreeNode file = new DefaultMutableTreeNode("file1.txt");
        folder.add(file);
        file = new DefaultMutableTreeNode("file2.txt");
        folder.add(file);
        rootNode.add(folder);
        folder = new DefaultMutableTreeNode("folder2");
        file = new DefaultMutableTreeNode("file1.txt");
        folder.add(file);
        file = new DefaultMutableTreeNode("file2.txt");
        folder.add(file);
        file = new DefaultMutableTreeNode("file3.txt");
        folder.add(file);
        rootNode.add(folder);
    }
    public void setTitle(String title)
    {
        border.setBorder(BorderFactory.createTitledBorder(title));
    }
}

class TreeTransferHandler extends TransferHandler 
{          
    private DataFlavor nodesFlavor;  
    private DataFlavor[] flavors = new DataFlavor[1];  
    private DefaultMutableTreeNode[] nodesToRemove;  
    public TreeTransferHandler()
    {
        super();
        try 
        {  
            String mimeType = DataFlavor.javaJVMLocalObjectMimeType +  
            ";class="" +  
            DefaultMutableTreeNode[].class.getName() +  
            """;  
            nodesFlavor = new DataFlavor(mimeType);  
            flavors[0] = nodesFlavor;  
        } 
        catch(ClassNotFoundException e) 
        {  
            System.out.println("ClassNotFound: " + e.getMessage());  
        } 
    }
    public boolean importData(TransferHandler.TransferSupport support) 
    {
        Transferable data = support.getTransferable();
        if(!canImport(support)) 
        {  
            return false;  
        }  
        // Extract transfer data.  
        List<DefaultMutableTreeNode> nodes =  new ArrayList<DefaultMutableTreeNode>();
        try 
        {  
            System.out.println("IMPORT DATA");
            nodes = (List<DefaultMutableTreeNode>) data.getTransferData(nodesFlavor);
            /*List<File> files = (List<File>)data.getTransferData(DataFlavor.javaFileListFlavor);  
            System.out.println("File size: " + nodes.size());
            for(File f : files)
            {
                System.out.println("File: "+f.getName());
            }*/
        } 
        catch(UnsupportedFlavorException ufe) 
        {  
            System.out.println("UnsupportedFlavor: " + ufe.getMessage());  
        } 
        catch(java.io.IOException ioe) 
        {  
            System.out.println("I/O error: " + ioe.getMessage());  
        }  
        catch(Exception e)
        {
            e.printStackTrace();
        }
        // Get drop location info inside the tree.  
        JTree.DropLocation dl =  
            (JTree.DropLocation)support.getDropLocation();  
        int childIndex = dl.getChildIndex();  
        TreePath dest = dl.getPath();  
        DefaultMutableTreeNode parent = (DefaultMutableTreeNode)dest.getLastPathComponent();  
        JTree tree = (JTree)support.getComponent();  
        DefaultTreeModel model = (DefaultTreeModel)tree.getModel();  
        // Configure for drop mode.  
        int index = childIndex;    // DropMode.INSERT  
        if(childIndex == -1) // DropMode.ON  
            index = parent.getChildCount();  
        // Add data to model.  
        for(int i = 0; i < nodes.size(); i++) 
        {  
            model.insertNodeInto(nodes.get(i), parent, index++);
        }  
        // Remove nodes saved in nodesToRemove in createTransferable.  
        for(int i = 0; i < nodesToRemove.length; i++) 
        {  
            model.removeNodeFromParent(nodesToRemove[i]); 
        }  
        return true;  
    } 
    public boolean canImport(TransferHandler.TransferSupport support) 
    {  
        if(!support.isDrop()) 
            return false;  
        support.setShowDropLocation(true);  
        if(!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor) 
                && !support.isDataFlavorSupported(nodesFlavor)) 
            return false;  
        // Do not allow a drop on the drag source selections.  
        JTree.DropLocation dl = (JTree.DropLocation)support.getDropLocation();  
        JTree tree = (JTree)support.getComponent();  
        int dropRow = tree.getRowForPath(dl.getPath());  
        int[] selRows = tree.getSelectionRows();  
        if(selRows != null)
        {
            for(int i = 0; i < selRows.length; i++) 
            {  
                if(selRows[i] == dropRow) 
                    return false;   
            }  
        }
        //Do not allow a drop on a File (leaf)
        try
        {
            TreePath targetPath = tree.getDropLocation().getPath();
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) targetPath.getLastPathComponent();
            if(node.isLeaf())
            {
                return false;
            }
        }
        catch(Exception ex)
        {
            System.out.println(ex.getMessage());
            return false;
        }
        // Do not allow a non-leaf node to be copied to a level  
        // which is less than its source level.  
        TreePath dest = dl.getPath();  
        DefaultMutableTreeNode target = (DefaultMutableTreeNode)dest.getLastPathComponent();  
        TreePath path = tree.getPathForRow(selRows[0]);  
        DefaultMutableTreeNode firstNode = (DefaultMutableTreeNode)path.getLastPathComponent();  
        if(firstNode.getChildCount() > 0 && target.getLevel() < firstNode.getLevel()) 
        {  
            return false;  
        }  
        return true;   
    }  

    //Do i have to use exportDone ?
    protected void exportDone(JComponent source, Transferable data, int action)
    {  
        if((action & MOVE) == MOVE) 
        {  
            //GET THE FILE DESTINATION FOLDER
            //LAUNCH THE DOWNLOAD FILE PROCESS
        }  
    }  
    protected Transferable createTransferable(JComponent c) 
    {  
        JTree tree = (JTree)c;  
        TreePath[] paths = tree.getSelectionPaths();  
        if(paths != null) 
        {  
            // Make up a node array of copies for transfer and  
            // another for/of the nodes that will be removed in  
            // exportDone after a successful drop.  
            ArrayList<DefaultMutableTreeNode> copies = new ArrayList<DefaultMutableTreeNode>();  
            ArrayList<DefaultMutableTreeNode> toRemove = new ArrayList<DefaultMutableTreeNode>();  
            //Fake files created in order to allow the export on explorer
            ArrayList<File> fakeFiles = new ArrayList<File>(); 
            DefaultMutableTreeNode node = (DefaultMutableTreeNode)paths[0].getLastPathComponent();  
            DefaultMutableTreeNode copy = copy(node);  
            copies.add(copy);  
            toRemove.add(node);  
            for(int i = 1; i < paths.length; i++) 
            {  
                DefaultMutableTreeNode next = (DefaultMutableTreeNode)paths[i].getLastPathComponent();  
                // Do not allow higher level nodes to be added to list.  
                if(next.getLevel() < node.getLevel()) 
                {  
                    break;  
                } 
                else if(next.getLevel() > node.getLevel())
                {  // child node  
                    copy.add(copy(next));  
                    // node already contains child  
                } 
                else 
                {                                        // sibling  
                    copies.add(copy(next));  
                    toRemove.add(next);  
                }  
            }  
            DefaultMutableTreeNode[] nodesToMove = copies.toArray(new DefaultMutableTreeNode[copies.size()]);  
            for(DefaultMutableTreeNode n : nodesToMove)
            {
                File f = new File(n.toString());
                fakeFiles.add(f);
            }
            nodesToRemove = toRemove.toArray(new DefaultMutableTreeNode[toRemove.size()]);  

            return new NodesTransferable(fakeFiles, Arrays.asList(nodesToMove));  
        }  
        return null;  
    }  
    /** Defensive copy used in createTransferable. */  
    private DefaultMutableTreeNode copy(DefaultMutableTreeNode node)
    {  
        return new DefaultMutableTreeNode(node);  
    }  
    public int getSourceActions(JComponent c) 
    {  
        return COPY_OR_MOVE;  
    }  
    public class NodesTransferable implements Transferable 
    {  
        private List<File> data = null;
        private List<DefaultMutableTreeNode> nodes = null;
        private DataFlavor[] flavors = new DataFlavor[2];
        public NodesTransferable(final List<File> data, final List<DefaultMutableTreeNode> nodes)
        {
            super();
            this.data = data;
            this.nodes = nodes;
            flavors[0] = DataFlavor.javaFileListFlavor;
            flavors[1] = nodesFlavor;
        }
        public DataFlavor[] getTransferDataFlavors() 
        {
            return flavors;
        }
        public boolean isDataFlavorSupported(final DataFlavor flavor) 
        {
            return true;
        }
        public List<?> getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException, IOException 
        {
            if(flavor.equals(DataFlavor.javaFileListFlavor))
                return data;
            else if(flavor.equals(nodesFlavor))
                return nodes;
            else
            {
                System.out.println("Unsuported flavor");
                return null;
            }
        }
    }  
}

我可能搞错了,但是我不相信Java客户机知道JVM之外发生了丢失。我认为拖放的契约是每个客户端(程序)在拖放开始时负责推出数据,在拖放发生时负责拉出数据。您需要查看浏览器中是否有一个库来通知您此删除。

看看互联网,它看起来像这个例子:http://www.codeproject.com/Articles/591/Drag-And-Drop-between-JList-and-Windows-Explorer展示了如何在JList和资源管理器之间做到这一点。请注意,我还没有机会尝试这个方法,看看它是否有效。看起来有一个DataFlavor:

DataFlavor.javaFileListFlavor

这里是另一篇描述类似内容的文章:Swing应用程序->拖,拖到桌面/文件夹

最新更新