复制到全局剪贴板不适用于 Ubuntu 中的 Java

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14242719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 15:35:23  来源:igfitidea点击:

Copying to global clipboard does not work with Java in Ubuntu

javaswingubuntuawtcopy-paste

提问by Karussell

The following code from a standalone application works in ubuntu:

以下来自独立应用程序的代码适用于 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));
    }

}

Pasting (Ctrl+V) into a different application results in nothing; I expect "NOW". Calling the above code a second time gives the following exception:

将 (Ctrl+V) 粘贴到不同的应用程序中不会产生任何结果;我期待“现在”。第二次调用上面的代码会出现以下异常:

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

As a standalone application, this should work even after 2011 security changes. Copying via Ctrl+C from inside of a JTextField and then pasting elsewhere works.

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

Have been unsuccessful on ubuntu 11.04 with both the latest java7 (jdk1.7.0_10) and jdk1.6.0_33; It should workand does work as expected on windows 7 with the latest java7 and on mac osx 10.6 with java6_37. Also tried xubuntu 12.04 with those javas and it doesn't work there. Is this a linux/ubuntu bug?

在ubuntu 11.04上用最新的java7(jdk1.7.0_10)和jdk1.6.0_33都没有成功;它应该可以正常工作,并且可以在使用最新 java7 的 windows 7 和使用 java6_37 的 mac osx 10.6 上按预期工作。还用这些 java 尝试了 xubuntu 12.04,但在那里不起作用。这是一个 linux/ubuntu 错误吗?

Related question

相关问题

采纳答案by Jonathan Drapeau

I got the same problem with the application at my work and here's an article I've found that explain why and possible solutions. I hope it helps.

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

Why it happens

为什么会发生

Clipboard persistence is a bug that affects many programs under Ubuntu and other X11-based operating systems. Fixing it is a Google Summer of Code 2010 project. Wikipedia has a good overview of the issue. If you want to fix as a user, you can install Parcellite or another clipboard manager. If you want to fix it as a programmer, you can modify your program to conform to the ClipboardManager specification.

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

X-Window wiki

X-Window 维基

Using gnome libraryyou could call the store method on the clipboard and fix this. That's the only thing so far that seems to be worth trying. Also saw a similar thing for GTK but only in an Eclipse's bug.

使用 gnome 库,您可以调用剪贴板上的 store 方法并修复此问题。到目前为止,这是唯一值得尝试的事情。也看到了 GTK 类似的事情,但只在 Eclipse 的错误中。

回答by raffael

I tried your code with debian testing (7.0) and openjdk 7u3. The result is the same, but i think i found the Problem (Solution).

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

Content in the clipboard is only valid as long as the process exists. It works if i change your code to this:

剪贴板中的内容仅在进程存在时才有效。如果我将您的代码更改为:

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();
    }
}

The if statement prevent your code from throwing an exception when there is no usable content, which happens if you run your code once and the process ends.
The System.in.read() just keeps the process alive. While not press enter i can paste into another application and "NOW" comes out as expected.
Like this the code works every time for me.

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

Hope this helps.

希望这可以帮助。

回答by paulsm4

Q: Have you tried something like this:

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

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

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

permission java.awt.AWTPermission "accessClipboard";

permission java.awt.AWTPermission "accessClipboard";

See also:

也可以看看:

回答by albfan

Here you can show a test:

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

A TextArea (its default copy/paste actions works out of the box with any other app on ubuntu)

一个 TextArea(它的默认复制/粘贴操作与 ubuntu 上的任何其他应用程序一起开箱即用)

I have added two buttons which copy and paste from/to system clipboard

我添加了两个按钮,用于从/到系统剪贴板复制和粘贴

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);
    }
}

I think you must take care of:

我认为你必须照顾:

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

And see there is a DataFlavor.plainTextFlavorwhich maybe is what you need to use (although it is deprecated)

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

I have tested the code through java 1.4 to java 1.6 on Ubuntu 12.10, but the code where I extract it is in use since ubuntu 9.0 I recall.

我已经在 Ubuntu 12.10 上通过 java 1.4 到 java 1.6 测试了代码,但是我记得从 ubuntu 9.0 开始使用我提取它的代码。