Java中AWT拖放时出现奇怪错误

Java中AWT拖放时出现奇怪错误,java,swing,drag-and-drop,awt,Java,Swing,Drag And Drop,Awt,好的,这里是错误:java.awt.dnd.InvalidDnDOperationException:请求的操作无法由dnd系统执行,因为它未处于适当的状态。当我将一些文件放入程序(从桌面抓取)时,会出现错误。我正在使用Ubuntu16.04和Nautilus import javax.swing.*; import java.awt.datatransfer.DataFlavor; import java.awt.dnd.*; import java.io.File; import java.

好的,这里是错误:
java.awt.dnd.InvalidDnDOperationException:请求的操作无法由dnd系统执行,因为它未处于适当的状态
。当我将一些文件放入程序(从桌面抓取)时,会出现错误。我正在使用Ubuntu16.04和Nautilus

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;
}
}
import javax.swing.*;
导入java.awt.datatransfer.DataFlavor;
导入java.awt.dnd.*;
导入java.io.File;
导入java.util.List;
类UI扩展了JFrame{
列出文件;
UI(){
超级(“我的程序”);
此.setDefaultCloseOperation(关闭时退出);
此.setLayout(null);
此.setVisible(true);
此参数为.setresizeable(true);
这个。设置大小(800500);
这个.setExtendedState(最大化两个);
JTextField dropArea=getDropArea();
添加(dropArea);
}
私有JTextField getDropArea(){
JTextField dropArea=新的JTextField(“在此处放置文件”);
下降面积.立根(50,50,200,200);
setDropTarget(createNewDropTarget(dropArea));
返回区;
}
私有DropTarget createNewDropTarget(JTextField dropArea){
DropTarget dt=新的DropTarget(){
@凌驾
公共同步作废删除(DropTargetDropEvent dtde){
超级下降(dtde);
试一试{
dtde.acceptDrop(DnDConstants.ACTION\u COPY);
droppedFiles=(列表)dtde.getTransferable()。
getTransferData(DataFlavor.javaFileListFlavor);
setText(droppedFiles.get(0.getName());
}捕获(例外e){
e、 printStackTrace();
}
}
};
返回dt;
}
}

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

通过设置
DropTarget
的方式,无需调用
super.drop(dtde)。这实际上就是例外的原因。下面是
DropTarget.drop()的实现:

由于您没有使用侦听器初始化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();
            }
        });
    }
}
导入java.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.datatransfer.DataFlavor;
导入java.awt.dnd.DnDConstants;
导入java.awt.dnd.DropTarget;
导入java.awt.dnd.DropTargetAdapter;
导入java.awt.dnd.DropTargetDropEvent;
导入java.io.File;
导入java.util.List;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JTextField;
导入javax.swing.SwingUtilities;
公共类DDTest扩展了JPanel{
公共测试(){
setLayout(新的BorderLayout());
最终JTextField dropArea=新的JTextField(“此处放置文件”);
添加(删除区域);
新的DropTarget(dropArea,新的DropTargetAdapter(){
@凌驾
公共作废删除(DropTargetDropEvent dtde){
试一试{
dtde.acceptDrop(DnDConstants.ACTION\u COPY);
List droppedFiles=(List)dtde
.getTransferable().getTransferData(
DataFlavor.javaFileListFlavor);
setText(droppedFiles.get(0.getName());
}捕获(例外e){
e、 printStackTrace();
} 
}           
});
}
@凌驾
公共维度getPreferredSize(){
返回新维度(300200);
}
私有静态void createAndShowGUI(){
最终JFrame=新JFrame(“DDTest”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(新的DDTest());
frame.pack();
frame.setLocationByPlatform(真);
frame.setVisible(true);
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
}
PS:


请注意,使用可能很复杂,通常可以避免。请参阅以获取一些想法

通过设置
DropTarget
的方式,无需调用
super.drop(dtde)。这实际上就是例外的原因。下面是
DropTarget.drop()的实现:

由于您没有使用侦听器初始化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();
            }
        });
    }
}
导入java.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.datatransfer.DataFlavor;
导入java.awt.dnd.DnDConstants;
导入java.awt.dnd.DropTarget;
导入java.awt.dnd.DropTargetAdapter;
导入java.awt.dnd.DropTargetDropEvent;
导入java.io.File;
导入java.util.List;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JTextField;
导入javax.swing.SwingUtilities;
公共类DDTest扩展了JPanel{
公共测试(){
setLayout(新的BorderLayout());
最终JTextField dropArea=新的JTextField(“此处放置文件”);
添加(删除区域);
新的DropTarget(dropArea,新的DropTargetAdapter(){
@凌驾
公共作废删除(DropTargetDropEvent dtde){
试一试{
dtde.acceptDrop(DnDConstants.ACTION\u COPY);
List droppedFiles=(List)dtde
.getTransferable().getTransferData(
DataFlavor.javaFileListFlavor);
dropArea.setText(已删除