Java AWT 提供 java.awt.datatransfer 套件,配合 Toolkit.getSystemClipboard() 即可存取系統剪貼簿,實現跨應用程式的文字複製、貼上、剪下操作。本文以 Swing 元件示範完整實作流程。
Transferable 簡易實作,專門處理純文字。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);
}
}
Toolkit.getDefaultToolkit().getSystemClipboard()。StringSelection → clipboard.setContents()。clipboard.getContents() → 檢查 isDataFlavorSupported(DataFlavor.stringFlavor) → getTransferData()。JTextComponent.replaceRange("", start, end) 移除原文字。ImageSelection 實作 Transferable,配合 DataFlavor.imageFlavor。Transferable 回傳 List<File>,對應 DataFlavor.javaFileListFlavor。byte[],定義專屬 DataFlavor(需雙方協定)。SwingUtilities.invokeLater 保證。| 現象 | 原因 | 解決 |
|---|---|---|
| 貼上無反應 | 剪貼簿內容非文字 | 檢查 isDataFlavorSupported |
| 中文亂碼 | 編碼不一致 | 確保 JVM 與系統預設編碼皆為 UTF-8 |
| 安全例外 | Applet/WebStart 限制 | 簽署 JAR 或調整安全策略 |