java - Java 中 AWT 中的拖放出现奇怪错误

标签 java swing drag-and-drop awt

好吧,这里是错误:java.awt.dnd.InvalidDnDOperationException:DnD 系统无法执行请求的操作,因为它未处于适当的状态。当我将某些文件放入程序中(从桌面抓取)时,会出现错误。我正在使用 Ubuntu 16.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;
}
}

错误出现在初始化 DropFiles 的行上。 (在 try catch block 中)。

最佳答案

以某种方式设置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一些想法。

关于java - Java 中 AWT 中的拖放出现奇怪错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45989223/

相关文章:

javascript - jQuery UI 可拖动 : Custom Snap-To Method

java - 正则表达式匹配单词的一部分

java - Tomcat 连接器匹配属性警告

java - Amazon Alexa Web 服务总是给出 401

java - 在 JTable 中使列不可编辑

java - 如何修复 JFileChooser 的错误或避免阻止 JFC 显示快捷方式 (lnk) 文件夹的错误

java - 为什么Java中Swing GUI关闭后新线程也会退出

java - Android拖放多个 TextView

java - 与 Java 中的 ProcessBuilder 的混淆

drag-and-drop - jsTree-禁用拖动选项