Ky -
Ky -

Reputation: 32093

Why am I getting an InvalidDnDOperationException?

I'm sorry; I don't like asking "why am I getting exception?" questions on StackOverflow (bit ironic now that I think of it...), but I can't figure out the cause of this exception! I've searched for a solution, but those that popped up were either for a subtly different exception, when people were trying to access a Transferrable outside of an event handler, or not ever answered at all.

I'm trying to do this right inside the DropTargetListener#drop(DropTargetListener) method. I'm testing this by dragging a PNG from the same drive that the program is running on, which makes me think that the data is readily available. My relevant code and the resulting exception are below:

Code

(shortened for brevity, line numbers in comments, followed by => if it's an error line)

        // package declaration
        // imports

/*45 */ public class BHFileChooser extends JComponent implements DropTargetListener
/*46 */ {
            // object declaration 

            ...

            // initialization methods

            ...

/*186*/     @Override
/*187*/     public void dragEnter(DropTargetDragEvent dtde)
/*188*/     {
/*189*/         setState(State.EVALUATING);
/*190*/         setState(canAccept(dtde.getTransferable()) ? State.EVALUATED_ACCEPTABLE : State.EVALUATED_UNACCEPTABLE);
/*191*/         validate();
/*192*/     }
/*193*/ 
/*194*/     @Override
/*195*/     public void dragExit(DropTargetEvent dte)
/*196*/     {
/*197*/         setState(State.WAITING);
/*198*/         validate();
/*199*/     }
/*200*/ 
/*201*/     @Override public void dragOver(DropTargetDragEvent dtde){} // unused for now
/*202*/ 
/*203*/     @Override
/*204*/     public void dropActionChanged(DropTargetDragEvent dtde)
/*205*/     {
/*206*/         userAction = dtde.getDropAction();
/*207*/         validate();
/*208*/     }
/*209*/ 
/*210*/     @Override
/*211*/     public void drop(DropTargetDropEvent dtde)
/*212*/     {
/*213*/         setState(State.WAITING); // I use a finite-state machine to keep track of what's happening
/*214*/         setState(State.EVALUATING);
/*215*/         Transferable t = dtde.getTransferable();
/*216*/         try
/*217*/         {
/*218 =>*/          if (canAccept(t))
/*219*/                 try
/*220*/                 {
/*221*/                     setState(State.EVALUATED_ACCEPTABLE);
/*222*/                     File f = (File)t.getTransferData(DataFlavor.javaFileListFlavor);
/*223*/                     acceptFile(f);
/*224*/                 }
/*225*/                 catch (UnsupportedFlavorException ex)
/*226*/                 {
/*227*/                     setState(State.EVALUATED_UNACCEPTABLE);
/*228*/                 }
/*229*/                 catch (IOException ex)
/*230*/                 {
/*231*/                     Logger.getGlobal().log(Level.SEVERE, MESSAGE_IO_EXCEPTION, ex);
/*232*/                 }
/*233*/             else
/*234*/                 setState(State.EVALUATED_UNACCEPTABLE);
/*235*/         }
/*236*/         catch (Throwable th)
/*237*/         {
/*238*/             th.printStackTrace();
/*239*/             setState(State.EVALUATED_UNACCEPTABLE); // evaluation could not be completed, so we can't accept it
/*240*/             setState(State.WAITING);                // go back to waiting for another file
/*241*/         }
/*242*/         
/*243*/         validate();
/*244*/     }

            // more methods

            ...

/*267*/     public void acceptFile(File f)
/*268*/     {
/*269*/         if (fileFilter == null || fileFilter.accept(f))
/*270*/         {
/*271*/             setState(State.EVALUATED_ACCEPTABLE);
/*272*/             setState(State.LOADING);
/*273*/             file = f;
/*274*/             setState(State.LOADED);
/*275*/         }
/*276*/         else
/*277*/             setState(State.EVALUATED_UNACCEPTABLE);
/*278*/     }

            // more methods

            ...

/*311*/     private boolean canAccept(Transferable t)
/*312*/     {
/*313*/         try
/*314*/         {
/*315*/             System.out.println(Arrays.deepToString(t.getTransferDataFlavors()));
/*316*/             
/*317*/             if (!t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
/*318*/                 return false;
/*319*/             
/*320 =>*/          List<File> data = (List)t.getTransferData(DataFlavor.javaFileListFlavor); // the error occurs in here
/*321*/             if (fileFilter == null)
/*322*/                 return true;
/*323*/             return
/*324*/                 data.stream() // treat the list as a stream
/*325*/                 .noneMatch(   // return true if none match the following rule:
/*326*/                     (f) -> (                  // for each file
/*327*/                         !fileFilter.accept(f) // if the filter doesn't accept it
/*328*/                     )
/*329*/                 )
/*330*/             ;
/*331*/         }
/*332*/         catch (UnsupportedFlavorException ex){}
/*333*/         catch (IOException ex)
/*334*/         {
/*335*/             Logger.getLogger(BHFileChooser.class.getName()).log(Level.SEVERE, MESSAGE_IO_EXCEPTION, ex);
/*336*/         }
/*337*/         return false;
/*338*/     }

            ...

            // more methods

            ...

            // internal classes & enums like State
/*468*/ }

Exception

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 org.bh.tools.comps.BHFileChooser.canAccept(BHFileChooser.java:320)
    at org.bh.tools.comps.BHFileChooser.drop(BHFileChooser.java:218)
    at java.awt.dnd.DropTarget.drop(DropTarget.java:455)
    at sun.awt.dnd.SunDropTargetContextPeer.processDropMessage(SunDropTargetContextPeer.java:538)
    at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchDropEvent(SunDropTargetContextPeer.java:852)
    at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEvent(SunDropTargetContextPeer.java:776)
    at sun.awt.dnd.SunDropTargetEvent.dispatch(SunDropTargetEvent.java:48)
    at java.awt.Component.dispatchEventImpl(Component.java:4738)
    at java.awt.Container.dispatchEventImpl(Container.java:2292)
    at java.awt.Component.dispatchEvent(Component.java:4705)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
    at java.awt.LightweightDispatcher.processDropTargetEvent(Container.java:4611)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4457)
    at java.awt.Container.dispatchEventImpl(Container.java:2278)
    at java.awt.Window.dispatchEventImpl(Window.java:2739)
    at java.awt.Component.dispatchEvent(Component.java:4705)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:719)
    at java.awt.EventQueue$4.run(EventQueue.java:717)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:716)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Also, what does it mean by No drop current? I don't see this documented anywhere.

Upvotes: 4

Views: 2136

Answers (2)

maszter
maszter

Reputation: 3720

I think you should call:

dtde.acceptDrop(DragNDropConstants.ACTION_COPY_OR_MOVE);

Java 7 and newer:

dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);

before

dtde.getTransferable();

'Self defined getTransferable have no problem if you don't, Java's Transferable for native drag'n'drop operation needs this call.'

ref 1, ref 2

Upvotes: 15

StackUMan
StackUMan

Reputation: 105

I just encountered this problem aswell, but for a different reason than the one specified above. My fault lied in calling super.drop when overriding the drop method.

So this did not work

        @Override
        public synchronized void drop(DropTargetDropEvent dtde) {
            super.drop(dtde);
            try{
                dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                List<File> fileList = (List<File>) dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
                for(File f : fileList){
                    filesAssocTField.setText(f.getAbsolutePath());
                }
            } catch (Exception ex){
                System.out.println("caught exception in filesAssocTField drop target");
                ex.printStackTrace();
            }
        }

While this did

        @Override
        public synchronized void drop(DropTargetDropEvent dtde) {
            try{
                dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                List<File> fileList = (List<File>) dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
                for(File f : fileList){
                    filesAssocTField.setText(f.getAbsolutePath());
                }
            } catch (Exception ex){
                System.out.println("caught exception in filesAssocTField drop target");
                ex.printStackTrace();
            }
        }

Upvotes: 1

Related Questions