I doubt that this functionality can be useful for someone in 21st century. I’m sure no one else uses Swing now :) Anyway I got a business requirement to do that. I’ve been using Swing for 3 years, not so often and didn’t touch drag-and-drop in swing before. This task sounds pretty crazy at the beginning. I was sure that I can’t communicate in the Swing app with the outside world - I was wrong. First thing which I checked, I tried to drag a folder in project tree of IDEA and drop to the desktop and this worked. Next I started to google and found nothing which can help me with my task.
Here I started my experiments which produced following code.
To recognize drag-and-drop gestures here we have java.awt.dnd.DragSource. Let’s assume we need to have a draggable button on a frame.
JPanel panel = new JPanel();
JButton btn = new JButton("Draggable button");
new DragSource().createDefaultDragGestureRecognizer(
btn,
DnDConstants.ACTION_COPY_OR_MOVE,
(DragGestureEvent event) -> {
event.startDrag(DragSource.DefaultLinkDrop, new TransferData());
});
panel.add(btn);
add(panel);
If you try to drag the button your cursor will be shown as a draggable action happens. TransferData represents the way of data transfer. And it could be some thing like that:
private static class TransferData implements Transferable {
private Gson gson = new Gson();
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{
new DataFlavor(String.class, null)
};
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return true;
}
@Override
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
return gson.toJson(Data.createRandomData());
}
}
getTransferDataFlavors method tells DragSource which type of data will be transferred here.
getTransferData method returns the data itself. As you see I used Gson to serialize my business object to json.
Now we need to introduce the receiving side. It’ll be a plain html page. The most interesting part of it is javascript code. There we need to define listeners for for 3 events: dragover, dragenter, drop. It’s important to call preventDefault and stopPropagation to prevent others actions and make this code work in all browsers, Here is briefly explanation why we need to do that.
$('#dropArea').on('dragover',
function (e) {
e.preventDefault();
e.stopPropagation();
}
).on('dragenter',
function (e) {
e.preventDefault();
e.stopPropagation();
}
).on('drop',
function(e){
if(e.originalEvent.dataTransfer){
e.preventDefault();
e.stopPropagation();
var data = JSON.parse(
e.originalEvent.dataTransfer.getData('text')
);
//your stuff goes here
}
}
);
Here we go. The working example you can find in my github project with examples.