【问题标题】:Strange error with Drag and Drop in AWT in JavaJava中AWT中拖放的奇怪错误
【发布时间】:2017-08-31 20:02:11
【问题描述】:

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

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;
}
}

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

【问题讨论】:

    标签: java swing drag-and-drop awt


    【解决方案1】:

    以您设置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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-02
      • 1970-01-01
      • 1970-01-01
      • 2012-05-03
      • 1970-01-01
      • 2011-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多