Java拖放自定义光标

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

我怀疑我将不得不使用AWT DnD支持来做到这一点,但我希望尽可能避免这种情况。

通过深入研究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 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); } }