Java DnD (Drag and Drop) 基於 java.awt.dnd 與 java.awt.datatransfer 兩大包。核心概念:
Transferable)。DataFlavor (MIME 類型)。public class DnDDemo extends JFrame
implements DragGestureListener, DragSourceListener, DropTargetListener {
private final DragSource dragSource = DragSource.getDefaultDragSource();
private final JLabel lblSource = new JLabel("Hello World!", SwingConstants.CENTER);
private final JTextField txtTarget = new JTextField();
private final DropTarget dropTarget;
public DnDDemo() {
setLayout(new BorderLayout());
add(lblSource, BorderLayout.NORTH);
add(txtTarget, BorderLayout.SOUTH);
setSize(400, 150);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// 1. 註冊拖曳源
dragSource.createDefaultDragGestureRecognizer(lblSource,
DnDConstants.ACTION_COPY_OR_MOVE, this);
// 2. 註冊放置目標
dropTarget = new DropTarget(txtTarget, DnDConstants.ACTION_COPY_OR_MOVE, this);
}
// === DragGestureListener ===
public void dragGestureRecognized(DragGestureEvent dge) {
Transferable t = new StringSelection(lblSource.getText());
dge.startDrag(DragSource.DefaultCopyDrop, t, this);
}
// === DragSourceListener (視覺回饋) ===
public void dragEnter(DragSourceDragEvent dsde) {
dsde.getDragSourceContext().setCursor(
(dsde.getDropAction() & DnDConstants.ACTION_COPY) != 0
? DragSource.DefaultCopyDrop : DragSource.DefaultCopyNoDrop);
}
public void dragOver(DragSourceDragEvent dsde) {}
public void dropActionChanged(DragSourceDragEvent dsde) {}
public void dragExit(DragSourceEvent dse) {}
public void dragDropEnd(DragSourceDropEvent dsde) {}
// === DropTargetListener ===
public void drop(DropTargetDropEvent dtde) {
try {
Transferable t = dtde.getTransferable();
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
dtde.acceptDrop(dtde.getDropAction());
String s = (String) t.getTransferData(DataFlavor.stringFlavor);
txtTarget.setText(txtTarget.getText() + s);
dtde.dropComplete(true);
} else {
dtde.rejectDrop();
}
} catch (Exception ex) { ex.printStackTrace(); dtde.rejectDrop(); }
}
public void dragEnter(DropTargetDragEvent dtde) {}
public void dragOver(DropTargetDragEvent dtde) {}
public void dropActionChanged(DropTargetDragEvent dtde) {}
public void dragExit(DropTargetEvent dte) {}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new DnDDemo().setVisible(true));
}
}
| 介面/類 | 核心方法 | 說明 |
|---|---|---|
DragSource | createDefaultDragGestureRecognizer | 綁定元件、動作類型、手勢監聽器 |
DragGestureListener | dragGestureRecognized | 建立 Transferable、呼叫 startDrag |
Transferable | getTransferDataFlavors, isDataFlavorSupported, getTransferData | 資料封裝,支援多種 MIME 類型 |
DropTarget | 建構子綁定元件、動作、監聽器 | 自動處理原生 DnD 協議 |
DropTargetListener.drop | acceptDrop, getTransferData, dropComplete | 接收資料、寫入目標元件、通知完成 |
Transferable 支援自定義物件序列化 (如 application/x-java-serialized-object)。DataFlavor.imageFlavor、DataFlavor.javaFileListFlavor (返回 List)。JTable、JList、JTree 設定 setDragEnabled(true)、setDropMode(DropMode.INSERT) 即可獲得基本 DnD,無需手寫監聽器。Serializable 並使用 java.io.serialization Flavor。