【问题标题】:Copying to global clipboard does not work with Java in Ubuntu复制到全局剪贴板不适用于 Ubuntu 中的 Java
【发布时间】:2012-12-23 22:37:55
【问题描述】:

以下来自独立应用程序的代码在 ubuntu 中运行:

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;

public class ClipboardTest {

    public static void main(String[] args) throws Exception {
        Clipboard clipBoard = Toolkit.getDefaultToolkit().getSystemClipboard();        
        // print the last copied thing
        System.out.println(clipBoard.getContents(null).getTransferData(DataFlavor.stringFlavor));
        StringSelection data = new StringSelection("NOW");
        clipBoard.setContents(data, data);
        // prints NOW
        System.out.println(clipBoard.getContents(null).getTransferData(DataFlavor.stringFlavor));
    }

}

粘贴 (Ctrl+V) 到不同的应用程序没有任何结果;我期待“现在”。再次调用上述代码会出现以下异常:

Exception in thread "main" java.awt.datatransfer.UnsupportedFlavorException: Unicode String
    at sun.awt.datatransfer.ClipboardTransferable.getTransferData(ClipboardTransferable.java:160)

作为一个独立的应用程序,即使在2011 security changes 之后也应该可以工作。通过 Ctrl+C 从 JTextField 内部复制,然后粘贴到其他地方。

在 ubuntu 11.04 上使用最新的 java7 (jdk1.7.0_10) 和 jdk1.6.0_33 均未成功;它should work 并在具有最新 java7 的 windows 7 和具有 java6_37 的 mac osx 10.6 上按预期工作。还用这些java尝试了xubuntu 12.04,但它在那里不起作用。这是 linux/ubuntu 的错误吗?

Related question

【问题讨论】:

  • 如需尽快获得更好的帮助,请发帖SSCCE
  • 你可以从tutorial examples开始。
  • 我不需要教程。正如我所说,这有效(在 windows+mac 上)但在 ubuntu 上无效。这里有 ubuntu 的人可以检查它是否适合他?
  • 对我来说,“以管理员身份运行”解决了这个问题。

标签: java swing ubuntu awt copy-paste


【解决方案1】:

我在工作中遇到了与应用程序相同的问题,这是我发现的一篇文章,解释了原因和可能的解决方案。希望对你有帮助。

Why it happens

剪贴板持久性是一个影响 Ubuntu 和其他基于 X11 的操作系统下的许多程序的错误。修复它是 Google Summer of Code 2010 项目。维基百科对这个问题有很好的概述。如果您想以用户身份进行修复,您可以安装 Parcellite 或其他剪贴板管理器。如果您想以程序员的身份对其进行修复,您可以修改您的程序以符合 ClipboardManager 规范。

X-Window wiki

Using gnome library 你可以调用剪贴板上的 store 方法来解决这个问题。到目前为止,这似乎是唯一值得尝试的事情。也看到了 GTK 的类似情况,但仅在 Eclipse 的错误中。

【讨论】:

  • 看来你找到了真正的原因+痛苦!谢谢!
  • 虽然我不明白为什么会这样(你的维基百科链接)。我了解不错的选择时复制机制与通过 CTRL+C 复制的区别
  • 对不起,找第二条的时候搞错了,应该是第二个链接。我的理解是,由于linux下的剪贴板不会将数据存储在一个永久的地方,并且只保留一个参考,当应用程序丢失时,数据也是如此。编辑了链接。
【解决方案2】:

我使用 debian testing (7.0) 和 openjdk 7u3 尝试了您的代码。结果是一样的,但我想我找到了问题(解决方案)。

剪贴板中的内容仅在进程存在时才有效。如果我将您的代码更改为以下内容,它会起作用:

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;

public class ClipboardTest {

    public static void main(String[] args) throws Exception {
        Clipboard clipBoard = Toolkit.getDefaultToolkit().getSystemClipboard();
        // print the last copied thing
        Transferable t = clipBoard.getContents(null);
        if (t.isDataFlavorSupported(DataFlavor.stringFlavor))
            System.out.println(t.getTransferData(DataFlavor.stringFlavor));
        StringSelection data = new StringSelection("NOW");
        clipBoard.setContents(data, data);
        // prints NOW
        System.out.println(clipBoard.getContents(null).getTransferData(DataFlavor.stringFlavor));
        System.in.read();
    }
}

if 语句可防止您的代码在没有可用内容时引发异常,如果您运行代码一次并且进程结束,就会发生这种情况。
System.in.read() 只是保持进程活着。虽然不按回车键,但我可以粘贴到另一个应用程序中,“现在”按预期出现。
像这样,代码每次都对我有用。

希望这会有所帮助。

【讨论】:

  • 是的,如果是必要的..但​​保持流程开放是关键!!非常感谢!粘贴到其他应用程序确实有效。现在奇怪的部分开始了。粘贴到我的 Java 应用程序中的行为也与您描述的完全一样。但是将其粘贴到 NetBeans 会导致系统剪贴板内容!当我停止 ClipboardTest 时,内容立即更改为“NOW”(而“粘贴”到本机应用程序会导致空字符串)。很奇怪。如果没有其他人找到确切的原因,我会给你学分。再次感谢!
  • 我不完全理解新的奇怪行为。你能给我一步一步的解释来重现吗?您还可以检查您是否正在使用剪贴板历史记录应用程序并使用设置进行播放。我记得几年前 klipper 和 java 的一个问题。
  • 1.运行修改后的 ClipboardTest 2. 粘贴到本机应用程序 => "NOW" 3. 粘贴到 Netbeans => "something different" 4. 停止 ClipboardTest 5. 粘贴到 Netbeans => "NOW"
  • 这似乎是netbeans的问题。我能够重现它。如果我在 netbeans 之外的命令行上启动 ClipboardTest,它不会发生。而且它也不会发生在eclipse中。
  • 非常感谢!你认为整个事情都是一个 ubuntu 错误吗?
【解决方案3】:

问:你有没有尝试过这样的事情:

gksudo gedit /opt/java/64/jre1.7.0_04/lib/security/java.policy =>

permission java.awt.AWTPermission "accessClipboard";

另见:

【讨论】:

  • 嘿,正如我所说,这与安全策略无关。因为 1. 它不是一个小程序(我从命令行运行它) 2. 它在 mac+windows 下工作 3. 即使在引入了这个限制的 jdk 上它也不起作用 4. 已经有“权限 java.security .AllPermission;"
  • 你有没有尝试设置Java策略?或者查看其他链接中的其他建议?还是您只是“假设”它们没有任何关系?
  • 另一个问题:如果我要让它在当前版本上运行(Ubuntu 12.04 LTS/32 位;我已经有几年没有玩过任何旧版本了),你会愿意升级到那个版本吗?
  • 如果策略已经有 AllPermission,我应该怎么做?我试图用你建议的替换那个 AllPermission - 不起作用。另请参阅问题 - 我现在在 12.04(xubuntu 但没关系)。
  • 还尝试将此添加到 java.policy 中的“授予所有域的默认权限”中 - 不起作用。这适用于您的 ubuntu 12.04 吗?
【解决方案4】:

在这里你可以展示一个测试:

TextArea(它的默认复制/粘贴操作可与 ​​ubuntu 上的任何其他应用程序一起使用)

我添加了两个按钮,可以从/向系统剪贴板复制和粘贴

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.ActionEvent;
import java.io.IOException;

public class PruebaClipboard {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setTitle("Copy/Paste");
        frame.getContentPane().setLayout(new BorderLayout());
        JPanel btnPanel = new JPanel();
        JButton btnCopy = new JButton("copy");
        JButton btnPaste = new JButton("paste");
        btnPanel.add(btnCopy);
        btnPanel.add(btnPaste);
        final JTextArea textComp = new JTextArea(7,15);

        Action copyAction = new AbstractAction("copy") {
            public void actionPerformed(ActionEvent e) {
                Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                StringSelection stringSelection = new StringSelection(textComp.getText());
                clipboard.setContents(stringSelection, stringSelection);
            }
        };

        btnCopy.setAction(copyAction);
        Action pasteAction = new AbstractAction("paste") {
            public void actionPerformed(ActionEvent e) {
                Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                //odd: the Object param of getContents is not currently used
                Transferable contents = clipboard.getContents(null);
                boolean hasTransferableText = (contents != null) && contents.isDataFlavorSupported(DataFlavor.stringFlavor);
                if (hasTransferableText) {
                    try {
                        String result = "";
                        result = (String) contents.getTransferData(DataFlavor.stringFlavor);
                        textComp.append(result);
                    } catch (UnsupportedFlavorException ex) {
                        //highly unlikely since we are using a standard DataFlavor
                        System.out.println(ex);
                        ex.printStackTrace();
                    } catch (IOException ex) {
                        System.out.println(ex);
                        ex.printStackTrace();
                    }
                }
            }
        };
        btnPaste.setAction(pasteAction);

        frame.getContentPane().add(textComp);
        frame.getContentPane().add(btnPanel, BorderLayout.SOUTH);

        frame.setSize(new Dimension(400, 300));
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

我认为你必须照顾:

boolean hasTransferableText = (contents != null) && contents.isDataFlavorSupported(DataFlavor.stringFlavor);

看看有一个DataFlavor.plainTextFlavor 可能是你需要使用的(虽然它已被弃用)

我已经在 Ubuntu 12.10 上测试了从 java 1.4 到 java 1.6 的代码,但我提取它的代码自 ubuntu 9.0 起就在使用了。

【讨论】:

  • 这不是我一直要求的
猜你喜欢
  • 2013-01-05
  • 2012-09-24
  • 2020-04-23
  • 1970-01-01
  • 2021-11-19
  • 2011-04-05
  • 1970-01-01
  • 2020-10-18
相关资源
最近更新 更多