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

Java Swing 實作剪貼簿複製、貼上、剪下功能

     編輯:Java 相關知識

前言

Java AWT 提供 java.awt.datatransfer 套件,配合 Toolkit.getSystemClipboard() 即可存取系統剪貼簿,實現跨應用程式的文字複製、貼上、剪下操作。本文以 Swing 元件示範完整實作流程。

核心類別說明

  • Clipboard:系統剪貼簿代表,單例模式。
  • Transferable:可傳輸資料介面,封裝資料內容與支援的 DataFlavor。
  • StringSelection:Transferable 簡易實作,專門處理純文字。
  • DataFlavor.stringFlavor:代表 Unicode 文字格式的標準風味。

完整可執行範例

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

public class ClipboardDemo implements ActionListener {
    private JFrame frame;
    private JTextArea sourceArea, targetArea;
    private JButton btnCopy, btnPaste, btnCut;
    private Clipboard clipboard;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(ClipboardDemo::new);
    }

    public ClipboardDemo() {
        initUI();
    }

    private void initUI() {
        frame = new JFrame("剪貼簿操作示範");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout(5, 5));
        frame.setSize(600, 450);
        frame.setLocationRelativeTo(null);

        // 頂部標題
        JLabel title = new JLabel("來源區域(可編輯) ←→ 目標區域(唯讀)", SwingConstants.CENTER);
        title.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
        frame.add(title, BorderLayout.NORTH);

        // 中央雙文字區
        JPanel center = new JPanel(new GridLayout(1, 2, 10, 0));
        sourceArea = new JTextArea("請在這裡輸入文字,選取後點擊「複製」或「剪下」", 15, 25);
        sourceArea.setLineWrap(true);
        sourceArea.setBorder(BorderFactory.createTitledBorder("來源文字區"));
        sourceArea.setWrapStyleWord(true);
        
        targetArea = new JTextArea(15, 25);
        targetArea.setLineWrap(true);
        targetArea.setWrapStyleWord(true);
        targetArea.setEditable(false);
        targetArea.setBorder(BorderFactory.createTitledBorder("目標文字區(貼上結果)"));
        targetArea.setBackground(Color.LIGHT_GRAY);

        center.add(new JScrollPane(sourceArea));
        center.add(new JScrollPane(targetArea));
        frame.add(center, BorderLayout.CENTER);

        // 底部按鈕列
        JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
        btnCopy = new JButton("複製 (Copy)");
        btnPaste = new JButton("貼上 (Paste)");
        btnCut = new JButton("剪下 (Cut)");
        
        for (JButton b : new JButton[]{btnCopy, btnPaste, btnCut}) {
            b.addActionListener(this);
            btnPanel.add(b);
        }
        frame.add(btnPanel, BorderLayout.SOUTH);

        // 取得系統剪貼簿
        clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();

        frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object src = e.getSource();
        
        if (src == btnCopy) {
            copyToClipboard();
        } else if (src == btnCut) {
            cutToClipboard();
        } else if (src == btnPaste) {
            pasteFromClipboard();
        }
    }

    /** 複製:不移除原文字 */
    private void copyToClipboard() {
        String selected = sourceArea.getSelectedText();
        if (selected != null && !selected.isEmpty()) {
            StringSelection selection = new StringSelection(selected);
            clipboard.setContents(selection, null);
            showStatus("已複製:" + selected.substring(0, Math.min(20, selected.length())) + "...");
        } else {
            showStatus("請先選取要複製的文字");
        }
    }

    /** 剪下:複製後從來源移除 */
    private void cutToClipboard() {
        String selected = sourceArea.getSelectedText();
        if (selected != null && !selected.isEmpty()) {
            StringSelection selection = new StringSelection(selected);
            clipboard.setContents(selection, null);
            // 移除選取區間文字
            sourceArea.replaceRange("", sourceArea.getSelectionStart(), sourceArea.getSelectionEnd());
            showStatus("已剪下:" + selected.substring(0, Math.min(20, selected.length())) + "...");
        } else {
            showStatus("請先選取要剪下的文字");
        }
    }

    /** 貼上:從剪貼簿讀取文字並附加到目標區 */
    private void pasteFromClipboard() {
        Transferable contents = clipboard.getContents(this);
        if (contents != null && contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            try {
                String text = (String) contents.getTransferData(DataFlavor.stringFlavor);
                targetArea.append(text);
                showStatus("已貼上:" + text.substring(0, Math.min(20, text.length())) + "...");
            } catch (Exception ex) {
                ex.printStackTrace();
                showStatus("貼上失敗:" + ex.getMessage());
            }
        } else {
            showStatus("剪貼簿無文字內容或格式不支援");
        }
    }

    private void showStatus(String msg) {
        frame.setTitle("剪貼簿操作示範 - " + msg);
    }
}

關鍵步驟解析

  1. 取得剪貼簿:Toolkit.getDefaultToolkit().getSystemClipboard()。
  2. 寫入資料:建立 StringSelection → clipboard.setContents()。
  3. 讀取資料:clipboard.getContents() → 檢查 isDataFlavorSupported(DataFlavor.stringFlavor) → getTransferData()。
  4. 剪下額外步驟:寫入剪貼簿後,呼叫 JTextComponent.replaceRange("", start, end) 移除原文字。

進階應用提示

  • 圖片支援:使用 ImageSelection 實作 Transferable,配合 DataFlavor.imageFlavor。
  • 檔案拖曳:實作 Transferable 回傳 List<File>,對應 DataFlavor.javaFileListFlavor。
  • 自定義物件:序列化物件為 byte[],定義專屬 DataFlavor(需雙方協定)。
  • 跨執行緒存取:剪貼簿操作需在 Event Dispatch Thread (EDT) 執行,範例已透過 SwingUtilities.invokeLater 保證。

常見錯誤排查

現象原因解決
貼上無反應剪貼簿內容非文字檢查 isDataFlavorSupported
中文亂碼編碼不一致確保 JVM 與系統預設編碼皆為 UTF-8
安全例外Applet/WebStart 限制簽署 JAR 或調整安全策略
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved