我定义了一个自定义画布样式组件,使用JPanel,可以支持将对象拖放到画布上。但我无法弄清如何使用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<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);
}
}