Drag n Drop: операция при перетаскивании файла из компонента в проводник, поиск и т. - PullRequest
3 голосов
/ 02 декабря 2011

У меня есть 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;
            }
        }
    }  
}

1 Ответ

0 голосов
/ 06 августа 2013

Я могу ошибаться, но я не верю, что Java-клиенту все-таки известно, что выпадение произошло за пределами JVM. Я полагаю, что контракт перетаскивания заключается в том, что каждый клиент (программа) отвечает за выталкивание данных при запуске перетаскивания и за извлечение данных при сбрасывании. Вам нужно посмотреть, есть ли в проводнике библиотека, чтобы уведомить вас об этом отбрасывании.

Глядя на интернет, он выглядит следующим образом: http://www.codeproject.com/Articles/591/Drag-And-Drop-between-JList-and-Windows-Explorer показывает, как сделать это между JList и проводником. Будьте предупреждены, что у меня не было возможности попробовать это, чтобы видеть, будет ли это работать. Похоже, есть DataFlavor:

DataFlavor.javaFileListFlavor

Вот еще одна статья, описывающая нечто подобное: Приложение Swing -> Перетащите на рабочий стол / папку

...