2

我使用 JPanel 定义了一个自定义画布样式组件,它将支持将对象拖到画布上。我似乎无法弄清楚如何使用 TransferHandler 将拖放(DnD)光标更改为自定义光标。例如,我想替换我自己的,而不是 DnD 期间的默认链接光标。有没有办法使用 TransferHandler 做到这一点?

我怀疑我将不得不使用 AWT DnD 支持来执行此操作,但如果可以的话,我希望避免这种情况。

4

1 回答 1

1

通过深入研究 TransferHandler 代码,我找到了解决方法。dragOver 方法是我更改光标的地方。我仍然认为我可能会遗漏一些简单的东西,但这暂时可以使用。

这两个静态类以及 exportAsDrag 中的代码是来自 TransferHandler 源代码的轻微修改副本。

编辑- 这就是我的工作方式。希望这可以帮助。欢迎提出建议。

    public class OverrideIconTransferHandler extends TransferHandler {
    private class MyDragGestureRecognizer extends DragGestureRecognizer {

        private static final long serialVersionUID = 1L;

        MyDragGestureRecognizer(DragGestureListener dgl) {
            super(DragSource.getDefaultDragSource(), null, NONE, dgl);
        }

        void gestured(JComponent c, MouseEvent e, int srcActions, int action) {
            setComponent(c);
            setSourceActions(srcActions);
            appendEvent(e);
            fireDragGestureRecognized(action, e.getPoint());
        }

        @Override
        protected void registerListeners() {
        }

        @Override
        protected void unregisterListeners() {
        }

    }

    private class MyDragHandler implements DragGestureListener, DragSourceListener {

        private boolean scrolls;

        @Override
        public void dragDropEnd(DragSourceDropEvent dsde) {
            DragSourceContext dsc = dsde.getDragSourceContext();
            JComponent c = (JComponent) dsc.getComponent();
            if (c.getTransferHandler() instanceof OverrideIconTransferHandler) {
                OverrideIconTransferHandler t = (OverrideIconTransferHandler) c.getTransferHandler();
                if (dsde.getDropSuccess()) {
                    t.exportDone(c, dsc.getTransferable(), dsde.getDropAction());
                } else {
                    t.exportDone(c, dsc.getTransferable(), NONE);
                }
            }
            c.setAutoscrolls(scrolls);
        }

        @Override
        public void dragEnter(DragSourceDragEvent dsde) {
        }

        @Override
        public void dragExit(DragSourceEvent dsde) {
        }

        @Override
        public void dragGestureRecognized(DragGestureEvent dge) {
            JComponent c = (JComponent) dge.getComponent();
            if (c.getTransferHandler() instanceof OverrideIconTransferHandler) {
                OverrideIconTransferHandler th = (OverrideIconTransferHandler) c.getTransferHandler();
                Transferable t = th.createTransferable(c);
                if (t != null) {
                    scrolls = c.getAutoscrolls();
                    c.setAutoscrolls(false);
                    try {
                        Image im = th.getDragImage();
                        if (im == null) {
                            dge.startDrag(null, t, this);
                        } else {
                            dge.startDrag(null, im, th.getDragImageOffset(), t, this);
                        }
                        return;
                    } catch (RuntimeException re) {
                        c.setAutoscrolls(scrolls);
                    }
                }

                th.exportDone(c, t, NONE);
            }
        }

        @Override
        public void dragOver(DragSourceDragEvent dsde) {
            if (dropCursorOverrides.containsKey(dsde.getDropAction())) {
                dsde.getDragSourceContext().setCursor(dropCursorOverrides.get(dsde.getDropAction()));
            } else {
                dsde.getDragSourceContext().setCursor(null);
            }
        }

        @Override
        public void dropActionChanged(DragSourceDragEvent dsde) {
        }
    }

    private static final long serialVersionUID = 1L;
    private MyDragGestureRecognizer myRecognizer = null;
    private final Map<Integer, Cursor> dropCursorOverrides = new HashMap<>();

    public void addDropCursorOverride(final int action, final Cursor cursor) throws IllegalArgumentException {
        if (!(action == COPY || action == MOVE || action == LINK || action == NONE)) {
            throw new IllegalArgumentException("Unknown Action Type");
        }
        dropCursorOverrides.put(action, cursor);
    }

    @Override
    public void exportAsDrag(JComponent comp, InputEvent e, int action) {
        if (comp.getTransferHandler() instanceof OverrideIconTransferHandler) {
            int srcActions = getSourceActions(comp);

            if (!(e instanceof MouseEvent) || !(action == COPY || action == MOVE || action == LINK) || (srcActions & action) == 0) {

                action = NONE;
            }

            if (action != NONE && !GraphicsEnvironment.isHeadless()) {
                if (myRecognizer == null) {
                    myRecognizer = new MyDragGestureRecognizer(new MyDragHandler());
                }
                myRecognizer.gestured(comp, (MouseEvent) e, srcActions, action);
            } else {
                exportDone(comp, null, NONE);
            }
        } else {
            super.exportAsDrag(comp, e, action);
        }
    }

    public void removeDropCursorOverride(final int action) throws IllegalArgumentException {
        if (!(action == COPY || action == MOVE || action == LINK || action == NONE)) {
            throw new IllegalArgumentException("Unknown Action Type");
        }
        dropCursorOverrides.remove(action);
    }
}
于 2012-12-05T20:24:06.307 回答