Java Drag and drop on OS X reports Move instead of Copy

心已入冬 提交于 2019-12-07 12:33:26

问题


Update/status: Bug is reported to Oracle and currently still open/unresolved: https://bugs.openjdk.java.net/browse/JDK-8054325

I've found a strange bug, which only manifests itself on Java 7 and 8 on OS X, not in Java 6, neither on Java 7 Windows.

Below is the extracted bug removing as much unneeded code as possible. It leaves us with a small table and a button, where we can drag the cell from the table on top of the button.

In our production code we are using a TransferHandler that has COPY_OR_MOVE as source action. We have two targets, one DropTarget accepts as MOVE, the other accepts as COPY. It seems that on OS X the JDK/JRE is broken because if the DropTarget accepts as COPY it reports in the TranferHandler is was a MOVE.

If we execute the code below on Java 6 (or Java 7 on Windows) it reports (as expected):

not move
is copy

But when we execute it on OS X Java 7 or Java 8 we get the following:

is move
not copy

I've tested and reported this to Oracle (bug report still pending). But since this will take a (loooong) while to get fixed, maybe someone here has an idea on how to make a 'clean' workaround?

I'd rather not have the drop target linked to the original component telling it the actual action (copy or move), this sound overly complex.

import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.TransferHandler;
import javax.swing.table.DefaultTableModel;

public class DropExample extends JPanel {

    public static void main(final String[] args) {
        final JFrame frame = new JFrame();
        frame.setSize(200, 100);
        frame.add(new DropExample());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public DropExample() {

        add(createTable());

        final JButton button = new JButton("Drop here");
        button.setDropTarget(new DropTarget(button, new DropTargetAdapter() {

            @Override
            public void drop(final DropTargetDropEvent dtde) {
                //Here we accept the drop, as COPY:
                dtde.acceptDrop(DnDConstants.ACTION_COPY);
                dtde.dropComplete(true);
            }
        }));
        add(button);
    }

    private JTable createTable() {

        final DefaultTableModel tm = new DefaultTableModel();
        tm.addColumn("Column 0");
        tm.addRow(new String[] { "Table 00" });

        final JTable table = new JTable(tm);
        table.setDragEnabled(true);
        table.setTransferHandler(new TransferHandler() {

            private static final long serialVersionUID = 1L;

            @Override
            public int getSourceActions(final JComponent c) {
                return COPY_OR_MOVE;
            }

            @Override
            protected Transferable createTransferable(final JComponent c) {
                return new StringSelection(c.toString());
            }

            @Override
            protected void exportDone(final JComponent source, final Transferable data, final int action) {
                System.out.println(((action & DnDConstants.ACTION_MOVE) > 0)?"is move":"not move");
                System.out.println(((action & DnDConstants.ACTION_COPY) > 0)?"is copy":"not copy");
                // On Java 7 it reports: "is move" and "not copy"
                // On Java 6 it (correctly) reports: "not move" and "is copy"
            }

        });
        return table;
    }
}

来源:https://stackoverflow.com/questions/25177678/java-drag-and-drop-on-os-x-reports-move-instead-of-copy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!