Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Drag-n-Drop files of specific extension on JFrame

I would like to implement DnD for my application to accept only files of certain extension (eg. wrl). I would like to change the cursor to a drag cursor if the file will be accepted and revert back to normal cursor when the file of wrong extension is drag and dropped.

I have been following the following tutorial/example from http://docs.oracle.com/javase/tutorial/uiswing/dnd/toplevel.html

The change that I make is in the canImport function

    public boolean canImport(TransferHandler.TransferSupport support) 
    {
        if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) 
        {
            return false;
        }

        Transferable t = support.getTransferable();

        try 
        {
          java.util.List<File> l = (java.util.List<File>)t.getTransferData(DataFlavor.javaFileListFlavor);
          if (l.size() != 1)
          {
            return false;
          }

          File f = l.get(0);

          String extension = f.getName().substring(f.getName().lastIndexOf("."));

          return extension.equalsIgnoreCase(".wrl");
        } 

        catch (UnsupportedFlavorException e) 
        {
            return false;
        } 
        catch (IOException e) 
        {
            return false;
        }
    }

This behaves correctly when I drag over in different files. However, when I drop the file, I get the following exception

Exception in thread "AWT-EventQueue-0" java.awt.dnd.InvalidDnDOperationException: No drop current
    at sun.awt.dnd.SunDropTargetContextPeer.getTransferData(SunDropTargetContextPeer.java:227)
    at sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:56)
    at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:359)
    at appl.TopLevelTransferHandlerDemo$1.canImport(TopLevelTransferHandlerDemo.java:207)
    at javax.swing.TransferHandler$DropHandler.drop(TransferHandler.java:1454)
    at java.awt.dnd.DropTarget.drop(DropTarget.java:434)
    at javax.swing.TransferHandler$SwingDropTarget.drop(TransferHandler.java:1193)
    at sun.awt.dnd.SunDropTargetContextPeer.processDropMessage(SunDropTargetContextPeer.java:519)
    at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchDropEvent(SunDropTargetContextPeer.java:832)
    at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEvent(SunDropTargetContextPeer.java:756)
    at sun.awt.dnd.SunDropTargetEvent.dispatch(SunDropTargetEvent.java:30)
    at java.awt.Component.dispatchEventImpl(Component.java:4487)
    at java.awt.Container.dispatchEventImpl(Container.java:2099)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577)
    at java.awt.LightweightDispatcher.processDropTargetEvent(Container.java:4312)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4163)
    at java.awt.Container.dispatchEventImpl(Container.java:2085)
    at java.awt.Window.dispatchEventImpl(Window.java:2478)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Any help greatly appreciated

like image 273
Leon Avatar asked Feb 26 '13 02:02

Leon


1 Answers

The last time I checked, this didn't work on Mac's, but that might have changed with Java 7...

enter image description hereenter image description hereenter image description here

Now, remember, when it comes to drag'n'drop, there is no easy answer that will do everything.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestDragNDrop {

    public static void main(String[] args) {
        new TestDragNDrop();
    }

    public TestDragNDrop() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel implements DropTargetListener {

        public enum DragState {

            Waiting,
            Accept,
            Reject
        }
        private DragState state = DragState.Waiting;
        private BufferedImage happy;
        private BufferedImage wait;
        private BufferedImage sad;

        public TestPane() {
            DropTarget dt = new DropTarget(
                    this,
                    DnDConstants.ACTION_COPY_OR_MOVE,
                    this,
                    true);

            setBackground(Color.BLACK);
            try {
                happy = ImageIO.read(getClass().getResource("/Happy.png"));
                wait = ImageIO.read(getClass().getResource("/Wait.png"));
                sad = ImageIO.read(getClass().getResource("/Sad.png"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 300);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            BufferedImage bg = null;
            switch (state) {
                case Waiting:
                    bg = wait;
                    break;
                case Accept:
                    bg = happy;
                    break;
                case Reject:
                    bg = sad;
                    break;
            }
            if (bg != null) {
                int x = (getWidth() - bg.getWidth()) / 2;
                int y = (getHeight() - bg.getHeight()) / 2;
                g.drawImage(bg, x, y, this);
            }
        }

        @Override
        public void dragEnter(DropTargetDragEvent dtde) {
            state = DragState.Reject;
            Transferable t = dtde.getTransferable();
            if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                try {
                    Object td = t.getTransferData(DataFlavor.javaFileListFlavor);
                    if (td instanceof List) {
                        state = DragState.Accept;
                        for (Object value : ((List) td)) {
                            if (value instanceof File) {
                                File file = (File) value;
                                String name = file.getName().toLowerCase();
                                if (!name.endsWith(".png")) {
                                    state = DragState.Reject;
                                    break;
                                }
                            }
                        }
                    }
                } catch (UnsupportedFlavorException | IOException ex) {
                    ex.printStackTrace();
                }
            }
            if (state == DragState.Accept) {
                dtde.acceptDrag(DnDConstants.ACTION_COPY);
            } else {
                dtde.rejectDrag();
            }
            repaint();
        }

        @Override
        public void dragOver(DropTargetDragEvent dtde) {
        }

        @Override
        public void dropActionChanged(DropTargetDragEvent dtde) {
        }

        @Override
        public void dragExit(DropTargetEvent dte) {
            state = DragState.Waiting;
            repaint();
        }

        @Override
        public void drop(DropTargetDropEvent dtde) {
            state = DragState.Waiting;
            repaint();
        }
    }
}
like image 170
MadProgrammer Avatar answered Sep 24 '22 19:09

MadProgrammer