在Java中的AWT中拖放的奇怪错误

问题描述:

好的,这里是错误:java.awt.dnd.InvalidDnDOperationException: The operation requested cannot be performed by the DnD system since it is not in the appropriate state。当我在程序中放置一些文件时(从桌面抓取),出现错误。我正在使用Ubuntu 16.04和Nautilus。在Java中的AWT中拖放的奇怪错误

import javax.swing.*; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.dnd.*; 
import java.io.File; 
import java.util.List; 

class UI extends JFrame { 
List<File> droppedFiles; 

UI(){ 
    super("My Program"); 
    this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    this.setLayout(null); 
    this.setVisible(true); 
    this.setResizable(true); 
    this.setSize(800, 500); 
    this.setExtendedState(MAXIMIZED_BOTH); 
    JTextField dropArea = getDropArea(); 
    this.add(dropArea); 
} 

private JTextField getDropArea(){ 
    JTextField dropArea = new JTextField("Drop file here"); 
    dropArea.setBounds(50, 50, 200, 200); 
    dropArea.setDropTarget(createNewDropTarget(dropArea)); 

    return dropArea; 
} 

private DropTarget createNewDropTarget(JTextField dropArea) { 
    DropTarget dt = new DropTarget(){ 
     @Override 
     public synchronized void drop(DropTargetDropEvent dtde) { 
      super.drop(dtde); 
      try { 
       dtde.acceptDrop(DnDConstants.ACTION_COPY); 
       droppedFiles = (List<File>) dtde.getTransferable(). 
         getTransferData(DataFlavor.javaFileListFlavor); 
       dropArea.setText(droppedFiles.get(0).getName()); 
      }catch (Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    }; 
    return dt; 
} 
} 

ErrorFind在初始化droppedFiles的行上出现。 (在try catch块中)。

以某种方式设置DropTarget无需拨打super.drop(dtde);。这实际上是例外的原因。这里是DropTarget.drop()实现:

public synchronized void drop(DropTargetDropEvent dtde) { 
    clearAutoscroll(); 

    if (dtListener != null && active) 
     dtListener.drop(dtde); 
    else { // we should'nt get here ... 
     dtde.rejectDrop(); 
    } 
} 

既然你不向监听器初始化DropTarget的下降被拒绝,随后呼叫getTransferable()失败InvalidDnDOperationException。如果您评论super.drop(dtde);,问题应该消失。一个更清洁的替代方案是创建一个监听器并将其传递给DropTarget。这里是一个小例子:

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.dnd.DnDConstants; 
import java.awt.dnd.DropTarget; 
import java.awt.dnd.DropTargetAdapter; 
import java.awt.dnd.DropTargetDropEvent; 
import java.io.File; 
import java.util.List; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 

public class DDTest extends JPanel { 
    public DDTest() { 
     setLayout(new BorderLayout()); 
     final JTextField dropArea = new JTextField("Drop file here"); 
     add(dropArea); 
     new DropTarget(dropArea, new DropTargetAdapter() { 
      @Override 
      public void drop(DropTargetDropEvent dtde) { 
       try { 
        dtde.acceptDrop(DnDConstants.ACTION_COPY); 
        List<File> droppedFiles = (List<File>) dtde 
          .getTransferable().getTransferData(
            DataFlavor.javaFileListFlavor); 
        dropArea.setText(droppedFiles.get(0).getName()); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      }   
     }); 
    } 

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

    private static void createAndShowGUI() { 
     final JFrame frame = new JFrame("DDTest"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     frame.add(new DDTest()); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 
} 

PS:

注意,使用absolute layout可能是复杂的,并且通常可以被避免。有些想法见A Visual Guide to Layout Managers