La copie dans le presse-papiers global ne fonctionne pas avec Java dans Ubuntu

Le code suivant d'une application autonome fonctionne dans 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));
    }

}

Coller (Ctrl + V) dans une application différente ne donne rien; j'attends "maintenant". L'appel du code ci-dessus une deuxième fois donne l'exception suivante:

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

En tant qu'application autonome, cela devrait fonctionner même après les modifications de sécurité 2011. Copier via Ctrl + C depuis l'intérieur D'un JTextField, puis coller ailleurs fonctionne.

Ont échoué sur ubuntu 11.04 avec les deux dernière java7 (jdk1.7.0_10) et jdk1.6.0_33; Il devrait fonctionner et fonctionne comme prévu sur windows 7 avec les derniers java7 et sur mac osx 10.6 avec java6_37. Aussi essayé xubuntu 12.04 avec ces javas et cela ne fonctionne pas là. Est - ce un bug linux/ubuntu?

Question Connexe

23
demandé sur Community 2013-01-09 21:15:38

4 réponses

J'ai eu le même problème avec l'application à mon travail et voici un article que j'ai trouvé qui explique pourquoi et les solutions possibles. J'espère que cela aide.

Pourquoi il arrive

La persistance du Presse-papiers est un bug qui affecte de nombreux programmes sous Ubuntu et d'autres systèmes d'exploitation basés sur X11. La fixation est un projet Google Summer of Code 2010. Wikipédia a un bon aperçu de la question. Si vous souhaitez corriger en tant qu'utilisateur, vous pouvez installer Parcellite ou un autre presse-papiers gestionnaire. Si vous voulez le réparer en tant que programmeur, vous pouvez modifier votre programme pour le rendre conforme à la spécification ClipboardManager.

X-Window wiki

En utilisant la bibliothèque gnome , Vous pouvez appeler la méthode store dans le presse-papiers et résoudre ce problème. C'est la seule chose à ce jour qui semble valoir la peine d'essayer. A également vu une chose similaire pour GTK mais seulement dans un bug D'Eclipse.

17
répondu Jonathan Drapeau 2014-10-29 19:55:16

J'ai essayé votre code avec debian testing (7.0) et openjdk 7u3. Le résultat est le même, mais je pense avoir trouvé le problème (Solution).

Le contenu du presse-papiers n'est valide que tant que le processus existe. Cela fonctionne si je change votre code à ceci:

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

L'instruction if empêche votre code de lancer une exception lorsqu'il n'y a pas de contenu utilisable, ce qui se produit si vous exécutez votre code une fois et que le processus se termine.
Le System.in.read() maintient simplement le processus en vie. Alors que pas appuyez sur Entrée je peux coller dans une autre application et "maintenant" sort comme prévu.
Ainsi, le code fonctionne à chaque fois pour moi.

J'espère que cela aide.

11
répondu raffael 2013-01-21 21:44:42

Q: Avez-vous essayé quelque chose comme ceci:

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

permission java.awt.AWTPermission "accessClipboard";

Voir aussi:

4
répondu paulsm4 2017-05-23 12:18:22

Ici vous pouvez montrer un test:

Une zone de texte (ses actions de copier/coller par défaut fonctionnent directement avec n'importe quelle autre application sur ubuntu)

J'ai ajouté deux boutons qui copient et collent depuis / vers le presse-papiers du système

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

Je pense que vous devez prendre soin de:

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

Et voir il y a un DataFlavor.plainTextFlavor qui est peut-être ce que vous devez utiliser (bien qu'il soit obsolète)

J'ai testé le code via java 1.4 à java 1.6 sur Ubuntu 12.10, mais le le code où je l'extrait est utilisé depuis ubuntu 9.0 je me souviens.

1
répondu albfan 2013-01-26 10:06:34