java - ClassCastException 对象无法在拖放中转换为 InputStream

标签 java swing drag-and-drop inputstream classcastexception

我下载了一个在java中在2个JList之间拖放的示例,我正在使用自己的对象,一切都工作得很好,但是每次我放下一个对象时我都会遇到这个异常,并且不知道为什么.

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.io.InputStream
    at sun.awt.datatransfer.DataTransferer.translateTransferable(DataTransferer.java:1372)
    at sun.lwawt.macosx.CDataTransferer.translateTransferable(CDataTransferer.java:131)
    at sun.awt.datatransfer.DataTransferer$6.run(DataTransferer.java:2380)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
    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)

这是我下载的示例。

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;

class ListItemTransferHandler extends TransferHandler {

private final DataFlavor localObjectFlavor;
private JList source = null;
private int[] indices = null;
private int addIndex = -1; //Location where items were added
private int addCount = 0;  //Number of items added.

public ListItemTransferHandler() {
    super();
    localObjectFlavor = new ActivationDataFlavor(Object[].class, DataFlavor.javaJVMLocalObjectMimeType, "Array of items");
}

@Override
protected Transferable createTransferable(JComponent c) {
    source = (JList) c;
    indices = source.getSelectedIndices();
    java.util.List transferedObjects = source.getSelectedValuesList();
    return new DataHandler(transferedObjects.toArray(), localObjectFlavor.getMimeType());
}

@Override
public boolean canImport(TransferSupport info) {
    return info.isDrop() && info.isDataFlavorSupported(localObjectFlavor);
}

@Override
public int getSourceActions(JComponent c) {
    return MOVE; //TransferHandler.COPY_OR_MOVE;
}

@SuppressWarnings("unchecked")
@Override
public boolean importData(TransferSupport info) {
    if (!canImport(info)) {
        return false;
    }
    JList target = (JList) info.getComponent();
    JList.DropLocation dl = (JList.DropLocation) info.getDropLocation();
    DefaultListModel listModel = (DefaultListModel) target.getModel();
    int index = dl.getIndex();
    //boolean insert = dl.isInsert();
    int max = listModel.getSize();
    if (index < 0 || index > max) {
        index = max;
    }
    addIndex = index;
    try {
        Object[] values = (Object[]) info.getTransferable().getTransferData(localObjectFlavor);
        for (int i = 0; i < values.length; i++) {
            int idx = index++;
            listModel.add(idx, values[i]);
            target.addSelectionInterval(idx, idx);
        }
        addCount = source.equals(target) ? values.length : 0;
        return true;
    } catch (UnsupportedFlavorException ufe) {
        ufe.printStackTrace();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
    return false;
}

@Override
protected void exportDone(JComponent c, Transferable data, int action) {
    cleanup(c, action == MOVE);
}

private void cleanup(JComponent c, boolean remove) {
    if (remove && indices != null) {
        //If we are moving items around in the same list, we
        //need to adjust the indices accordingly, since those
        //after the insertion point have moved.
        if (addCount > 0) {
            for (int i = 0; i < indices.length; i++) {
                if (indices[i] >= addIndex) {
                    indices[i] += addCount;
                }
            }
        }
        JList source = (JList) c;
        DefaultListModel model = (DefaultListModel) source.getModel();
        for (int i = indices.length - 1; i >= 0; i--) {
            model.remove(indices[i]);
        }
    }
    indices = null;
    addCount = 0;
    addIndex = -1;
 }
}

主类

public class DragNdrop extends JPanel {
private DragNdrop() {
    super(new BorderLayout());
    JPanel p = new JPanel(new GridLayout(1,2,10,0));
    TransferHandler h = new ListItemTransferHandler();
    p.setBorder(BorderFactory.createTitledBorder("Drag & Drop between JLists"));
    p.add(new JScrollPane(makeList(h)));
    p.add(new JScrollPane(makeList(h)));
    add(p);
    setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    setPreferredSize(new Dimension(320, 240));
}

private static JList<Color> makeList(TransferHandler handler) {
    DefaultListModel<Color> listModel = new DefaultListModel<>();
    listModel.addElement(Color.RED);
    listModel.addElement(Color.BLUE);
    listModel.addElement(Color.GREEN);
    listModel.addElement(Color.CYAN);
    listModel.addElement(Color.ORANGE);
    listModel.addElement(Color.PINK);
    listModel.addElement(Color.MAGENTA);
    JList<Color> list = new JList<>(listModel);
    list.setCellRenderer(new DefaultListCellRenderer() {
        @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            ((JLabel)c).setForeground((Color)value);
            return c;
        }
    });
    list.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    list.setDropMode(DropMode.INSERT);
    list.setDragEnabled(true);
    list.setTransferHandler(handler);
    return list;
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override public void run() {
            createAndShowGUI();
        }
    });
}
public static void createAndShowGUI() {
    try{
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }catch(ClassNotFoundException | InstantiationException |
           IllegalAccessException | UnsupportedLookAndFeelException ex) {
        ex.printStackTrace();
    }
    JFrame frame = new JFrame("DnDBetweenLists");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new DragNdrop());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
 }
}

最佳答案

我也有类似的情况,其 ListModel 包含自定义类的实例的 JList。我尝试使类可序列化,但这并没有消除 ClassCastException。最终,我找到了 2003 年的一篇帖子,其中发帖者已经确定了解决方案:您不想只使用 DataFlavor 中的裸 MIME 类型;您应该使用 DataFlavor 中的 MIME 类型。您需要附加“;class=”。

https://lists.apple.com/archives/java-dev/2003/Apr/msg00458.html

即使在我的例子中,正在传输的是一个对象数组:

SpecialObject[] myData...

ActivationDataFlavor 的构造如下所示:

new ActivationDataFlavor(SpecialObject[].class, "application/x-java-specialobject-array;class=com.foo.bar.baz.SpecialObject", "Array of SpecialObject")

以这种方式构造 ActivationDataFlavor 可以消除异常。

关于java - ClassCastException 对象无法在拖放中转换为 InputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24544926/

相关文章:

java - 在简单的 mvc Sp​​ring Web 项目中使用 slf4j 记录器

java - 如何使用 JMenuItem 将另一个类调用到我的主菜单类?

ajax - Play Framework :Ajax + 拖放 + 文件上传 + Controller 中的文件对象?

iPhone/iOS : How to implement Drag and Drop for subviews of a Scrollview?

javascript - 适用于 Internet Explorer 的文件夹拖放

java - Spring 的 ApplicationEvent 中的源是什么?

for 循环内的 Java If 语句,返回多个 int 值。

java - Long 为 64 位二进制字符串并将其添加到 8x8 数组

java - 如何检测 Swing 线程策略违规

java - 做了一个 "virus",需要提示