Linux下Java 5 Swing应用剪贴板内容无法在所有应用中粘贴该如何修复?
问题修复方案
问题根源
openSuse 10.0 基于旧版X11桌面环境,Java 5 默认的StringSelection仅提供少数Java内部识别的文本MIME类型,无法兼容部分仅支持TEXT/STRING、text/plain;charset=ISO-8859-1等传统X11剪贴板格式的旧应用。同时你开启了lineWrap和wrapStyleWord,JTextArea.getText()返回的换行符格式可能和部分旧应用期望的系统换行符不一致,也会导致粘贴失败。
修复步骤
1. 自定义兼容多格式的Transferable实现
替换默认的StringSelection,主动声明支持所有常用的文本剪贴板格式:
// 兼容Java 5的多格式文本Transferable实现 public class X11CompatibleTextTransferable implements Transferable, ClipboardOwner { private static final DataFlavor[] SUPPORTED_FLAVORS; static { List flavors = new ArrayList(); try { // 优先支持标准UTF-8文本 flavors.add(new DataFlavor("text/plain;charset=utf-8;class=java.lang.String")); // 兼容旧X11应用的ISO-8859-1文本 flavors.add(new DataFlavor("text/plain;charset=iso-8859-1;class=java.io.InputStream")); // 兼容Java原生和传统X11文本类型 flavors.add(DataFlavor.stringFlavor); flavors.add(DataFlavor.plainTextFlavor); flavors.add(new DataFlavor("UTF8_STRING;class=java.lang.String")); } catch (ClassNotFoundException e) { // 忽略当前环境不支持的格式即可 } SUPPORTED_FLAVORS = (DataFlavor[]) flavors.toArray(new DataFlavor[flavors.size()]); } private final String content; public X11CompatibleTextTransferable(String content) { // 统一替换为系统默认换行符,适配旧应用的换行识别规则 this.content = content.replaceAll("\\n", System.getProperty("line.separator")); } public DataFlavor[] getTransferDataFlavors() { return (DataFlavor[]) SUPPORTED_FLAVORS.clone(); } public boolean isDataFlavorSupported(DataFlavor flavor) { for (int i = 0; i < SUPPORTED_FLAVORS.length; i++) { if (SUPPORTED_FLAVORS[i].equals(flavor)) { return true; } } return false; } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (!isDataFlavorSupported(flavor)) { throw new UnsupportedFlavorException(flavor); } if (InputStream.class.isAssignableFrom(flavor.getRepresentationClass())) { String charset = flavor.getParameter("charset") == null ? "UTF-8" : flavor.getParameter("charset"); return new ByteArrayInputStream(content.getBytes(charset)); } else { return content; } } public void lostOwnership(Clipboard clipboard, Transferable contents) { // 空实现即可,Java 5要求传入有效的ClipboardOwner避免X11剪贴板内容异常丢失 } }
2. 修改原有复制逻辑
替换原有StringSelection为自定义实现,同时传入剪贴板所有者参数:
copyTextToClipboardButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String myString = decodedTextArea.getText(); X11CompatibleTextTransferable transferable = new X11CompatibleTextTransferable(myString); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard.setContents(transferable, transferable); } });
附加适配说明
如果仍有个别应用无法识别,可以在静态初始化块里按示例规则额外添加对应格式的DataFlavor即可,常见的旧X11文本格式还有STRING、text/plain等。
内容的提问来源于stack exchange,提问作者V. Pantis
相关产品推荐
相关产品推荐

