首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 滑鼠拖放功能實作完整指南

     編輯:Java 相關知識

前言

拖放 是圖形介面常見互動模式。Java 提供 java.awt.dnd 與 java.awt.datatransfer 套件支援拖放操作。本文完整解析拖放實作機制,並提供可執行的 JDragAndDropDemo 範例:將標籤文字拖曳至文字欄位追加內容。

核心概念

角色介面/類職責
拖曳來源DragSource, DragGestureListener, DragSourceListener提供資料、啟動拖曳、處理拖曳過程事件
放置目標DropTarget, DropTargetListener接收資料、處理放置事件
資料傳輸Transferable, DataFlavor封裝資料、定義資料格式

拖曳來源實作

1. 建立 DragGestureRecognizer

DragSource ds = DragSource.getDefaultDragSource();
int action = DnDConstants.ACTION_COPY_OR_MOVE;
ds.createDefaultDragGestureRecognizer(this, action, this);
  • this:拖曳來源元件(需實作 DragGestureListener)
  • action:拖曳動作類型(複製/移動)

2. 實作 DragGestureListener - 識別拖曳手勢

public void dragGestureRecognized(DragGestureEvent dge) {
    try {
        // 封裝要傳輸的資料
        Transferable tr = new StringSelection(this.getText());
        // 啟動拖曳:游標、資料、DragSourceListener
        dge.startDrag(DragSource.DefaultCopyNoDrop, tr, this);
    } catch (Exception e) { e.printStackTrace(); }
}

3. 實作 DragSourceListener - 處理拖曳過程

public void dragEnter(DragSourceDragEvent dsde) {
    DragSourceContext dsc = dsde.getDragSourceContext();
    int action = dsde.getDropAction();
    // 根據放置動作設定游標
    if ((action & DnDConstants.ACTION_COPY) != 0)
        dsc.setCursor(DragSource.DefaultCopyDrop);
    else
        dsc.setCursor(DragSource.DefaultCopyNoDrop);
}
// dragOver, dropActionChanged, dragExit, dragDropEnd 可留空

放置目標實作

1. 建立 DropTarget

new DropTarget(textField, DnDConstants.ACTION_COPY_OR_MOVE, this);
  • textField:放置目標元件
  • this:實作 DropTargetListener 的監聽器

2. 實作 DropTargetListener - 處理放置事件

public void drop(DropTargetDropEvent dtde) {
    try {
        Transferable tr = dtde.getTransferable();
        // 檢查資料格式是否支援
        if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            dtde.acceptDrop(dtde.getDropAction());
            String s = (String) tr.getTransferData(DataFlavor.stringFlavor);
            textField.setText(textField.getText() + s); // 追加文字
            dtde.dropComplete(true);
        } else {
            dtde.rejectDrop();
        }
    } catch (Exception e) { e.printStackTrace(); }
}
// dragEnter, dragOver, dropActionChanged, dragExit 可留空

完整可執行範例

DragJLabel - 可拖曳標籤

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;

public class DragJLabel extends JLabel 
    implements DragGestureListener, DragSourceListener {
    
    private DragSource ds = DragSource.getDefaultDragSource();
    
    public DragJLabel(String text, int alignment) {
        super(text, alignment);
        int action = DnDConstants.ACTION_COPY_OR_MOVE;
        ds.createDefaultDragGestureRecognizer(this, action, this);
    }
    
    @Override public void dragGestureRecognized(DragGestureEvent dge) {
        try {
            Transferable tr = new StringSelection(getText());
            dge.startDrag(DragSource.DefaultCopyNoDrop, tr, this);
        } catch (Exception e) { e.printStackTrace(); }
    }
    
    @Override public void dragEnter(DragSourceDragEvent dsde) {
        DragSourceContext dsc = dsde.getDragSourceContext();
        int action = dsde.getDropAction();
        dsc.setCursor((action & DnDConstants.ACTION_COPY) != 0 ? 
            DragSource.DefaultCopyDrop : DragSource.DefaultCopyNoDrop);
    }
    // 其他 DragSourceListener 方法留空
    @Override public void dragOver(DragSourceDragEvent e) {}
    @Override public void dropActionChanged(DragSourceDragEvent e) {}
    @Override public void dragExit(DragSourceEvent e) {}
    @Override public void dragDropEnd(DragSourceDropEvent e) {}
}

MainFrame - 主視窗(放置目標)

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;

public class MainFrame extends JFrame implements DropTargetListener {
    private JTextField textField = new JTextField();
    private DragJLabel label = new DragJLabel("Hello World!", SwingConstants.CENTER);
    
    public MainFrame() {
        initUI();
    }
    
    private void initUI() {
        setLayout(new BorderLayout());
        setSize(410, 114);
        setTitle("Java Drag and Drop Demo");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        textField.setFont(new Font("Dialog", Font.PLAIN, 14));
        add(textField, BorderLayout.SOUTH);
        add(label, BorderLayout.NORTH);
        
        // 註冊放置目標
        new DropTarget(textField, DnDConstants.ACTION_COPY_OR_MOVE, this);
    }
    
    @Override public void drop(DropTargetDropEvent dtde) {
        try {
            Transferable tr = dtde.getTransferable();
            if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                dtde.acceptDrop(dtde.getDropAction());
                String s = (String) tr.getTransferData(DataFlavor.stringFlavor);
                textField.setText(textField.getText() + s);
                dtde.dropComplete(true);
            } else { dtde.rejectDrop(); }
        } catch (Exception e) { e.printStackTrace(); }
    }
    // 其他 DropTargetListener 方法留空
    @Override public void dragEnter(DropTargetDragEvent e) {}
    @Override public void dragOver(DropTargetDragEvent e) {}
    @Override public void dropActionChanged(DropTargetDragEvent e) {}
    @Override public void dragExit(DropTargetEvent e) {}
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true));
    }
}

執行效果

  1. 啟動程式,視窗上方顯示 "Hello World!" 標籤,下方為文字欄位
  2. 按住標籤拖曳至文字欄位並放開
  3. 文字欄位追加 "Hello World!"
  4. 重複操作可持續追加

進階應用場景

  • 檔案拖放:DataFlavor.javaFileListFlavor 接收檔案清單
  • 圖片拖放:DataFlavor.imageFlavor 接收圖片資料
  • 跨應用拖放:支援從檔案總管/瀏覽器拖入 Java 應用
  • 自訂資料格式:實作 Transferable 定義專屬 DataFlavor

總結

Java AWT 拖放架構雖然 API 較繁瑣,但提供了完整的事件模型與資料傳輸抽象。核心在於:來源元件建立 DragGestureRecognizer、實作 DragGestureListener 啟動拖曳、目標元件建立 DropTarget、實作 DropTargetListener 接收資料。掌握此模式可實現豐富的桌面應用互動體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved