Копирование в глобальный буфер обмена не работает с Java в 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));
    }

}

Вставка (Ctrl + V) в другое приложение ничего не дает; Я ожидаю «СЕЙЧАС». Вызов вышеуказанного кода второй раз дает следующее исключение:

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

В качестве автономного приложения это должно работать даже после изменений безопасности 2011 года . Копирование через Ctrl + C изнутри JTextField, а затем вставку в другое место.

Неудачно на ubuntu 11.04 с последними java7 (jdk1.7.0_10) и jdk1.6.0_33; Он должен работать и работает как ожидается в Windows 7 с последним java7 и на mac osx 10.6 с java6_37. Также судимый xubuntu 12.04 с этими javas и там не работает. Это ошибка linux/ubuntu?

Смежный вопрос

23
nl ja de
Мне не нужен учебник. Как я уже сказал, это работает (на windows + mac), но не на ubuntu. Кто-то с ubuntu здесь и может проверить, работает ли он на него?
добавлено автор Karussell, источник
Чтобы лучше помочь, опубликуйте SSCCE .
добавлено автор Andrew Thompson, источник
Вы можете начать с примеров обучения .
добавлено автор trashgod, источник

4 ответы

У меня такая же проблема с приложением в моей работе, и вот статья, которую я нашел, которая объясняет, почему и возможные решения. Я надеюсь, что это помогает.

Почему это происходит

Сохранение буфера обмена - это ошибка, которая затрагивает многие программы под Ubuntu и другими операционными системами на базе X11. Фиксация - это проект Google Summer of Code 2010. В Википедии есть хороший обзор проблемы. Если вы хотите исправить себя как пользователь, вы можете установить Parcellite или другой менеджер буфера обмена. Если вы хотите исправить это как программист, вы можете изменить свою программу, чтобы она соответствовала спецификации ClipboardManager.

X-Window wiki

Using gnome library you 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.

17
добавлено
Хотя я не понимаю, почему это происходит (ваша ссылка в Википедии). Я понимаю разницу в хорошем механизме копирования на выбор против копирования через CTRL + C
добавлено автор Karussell, источник
Похоже, вы нашли настоящую причину + боль! Благодаря!
добавлено автор Karussell, источник
Извините, допустил ошибку, когда я нашел вторую статью, почему она должна быть второй ссылкой. Я понимаю, что, поскольку буфер обмена в Linux не сохраняет данные в постоянном месте и сохраняет только ссылку, когда приложение потеряно, так же как и данные. Отредактированы ссылки.
добавлено автор Jonathan Drapeau, источник

Я пробовал ваш код с 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();
    }
}

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.

Надеюсь это поможет.

11
добавлено
Я думаю, что не сохранять вещи в буфер обмена после закрытия процесса по дизайну. Для вещи с проблемой netbeans я бы догадался, что это ошибка в netbeans. Если это ошибка linux/ubuntu/debian, возможно, это произойдет и с eclipse.
добавлено автор raffael, источник
Это, по-видимому, проблема netbeans. Я могу воспроизвести его. Это не происходит, если я запускаю ClipboardTest в командной строке за пределами netbeans. И это также не происходит в затмении.
добавлено автор raffael, источник
Я не совсем понимаю новое странное поведение. Не могли бы вы дать мне пошаговое объяснение, чтобы воспроизвести? Вы также можете проверить, используете ли вы приложение для истории буфера обмена и играете с настройками. Я помню проблему с klipper и java несколько лет назад.
добавлено автор raffael, источник
1. Запуск измененного ClipboardTest 2. вставьте в собственное приложение => «СЕЙЧАС» 3. вставьте в Netbeans => «что-то другое» 4. остановите ClipboardTest 5. вставьте в Netbeans => «NOW»
добавлено автор Karussell, источник
Спасибо, см. Джонатанс за официальную ссылку
добавлено автор Karussell, источник
Почему вы думаете, что это по дизайну? Я имею в виду, что в других ОС он ведет себя иначе. Разве «дизайн» Java всегда должен быть одинаковым?
добавлено автор Karussell, источник
Большое спасибо! Вы думаете, что все это ошибка ubuntu?
добавлено автор Karussell, источник
да, если это необходимо .. но держать процесс открытым - это ключ! Большое спасибо! Вставка в другие приложения действительно работает. Теперь начинается странная часть. Вставка в мое приложение Java также ведет себя точно так, как вы описали. Но вставка его в NetBeans приводит к содержимому системного буфера обмена! И когда я останавливаю ClipboardTest, содержимое сразу меняется на «СЕЙЧАС» (тогда как «вставить» в собственные приложения приводит к пустой строке). очень странно. Я дам вам кредиты, если никто не найдет точной причины. Еще раз спасибо!
добавлено автор Karussell, источник

В: Вы пробовали что-то вроде этого:

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

разрешение java.awt.AWTPermission "accessClipboard";

Смотрите также:

4
добавлено
также попытался добавить это к «разрешениям по умолчанию, предоставленным всем доменам» в java.policy, - не работает. Это работает для вашего ubuntu 12.04?
добавлено автор Karussell, источник
Что я должен попробовать, если в политике уже есть AllPermission? Я попытался заменить этот AllPermission предложенным вами - не работает. Также, пожалуйста, см. Вопрос - я сейчас на 12.04 (xubuntu, но не имеет значения).
добавлено автор Karussell, источник
Эй, как я сказал, это не имеет ничего общего с политикой безопасности. Потому что 1. это НЕ апплет (я запускаю его из командной строки) 2. он работает под Mac + windows 3. он не работает даже с jdk, где это ограничение было введено 4. уже существует «разрешение java.security .AllPermission;»
добавлено автор Karussell, источник
Еще один вопрос: если мне нужно будет работать над текущей версией (Ubuntu 12.04 LTS/32 бит, прошло уже пару лет с тех пор, как я играл с любыми более старыми версиями), не могли бы вы перейти на эту версию?
добавлено автор paulsm4, источник
Вы даже выполнили try настройку политики Java? Или посмотрите на другие предложения в других ссылках? Или вы просто «предположили», что ничто из этого не имеет никакого отношения?
добавлено автор paulsm4, источник

Здесь вы можете показать тест:

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 , возможно, это то, что вам нужно использовать (хотя оно устарело)

Я тестировал код через java 1.4 до java 1.6 на Ubuntu 12.10, но код, в котором я его извлекаю, используется с ubuntu 9.0, я помню.

1
добавлено
это не то, о чем я просил
добавлено автор Karussell, источник
pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

Java & Co
Java & Co
2 370 участник(ов)

Можно обсуждать с матом и без всё, что касается жабы, вплоть до холиваров. НЕ ИМЕЕТ ОТНОШЕНИЯ К САЙТУ JAVARUSH.RU ПРАВИЛА - https://t.me/javarush/75723 Вакансии сюда - https://telegram.me/joinchat/B7IzvUCnfo6d8t3yIxKguQ По вопросам - @thedude

learn.java
learn.java
1 888 участник(ов)

Чат для начинающих и не только Статистика: https://combot.org/chat/-1001083535868 Основной чат - @jvmchat

RU.UBUNTU — сообщество пользователей Ubuntu
RU.UBUNTU — сообщество пользователей Ubuntu
1 681 участник(ов)

Сообщество пользователей Ubuntu Правила: https://telegra.ph/Pravila-soobshchestva-polzovatelej-ru-ubuntu-01-05 Список интересных групп и каналов: https://github.com/goq/telegram-list

Java Underground
Java Underground
169 участник(ов)

https://vk.com/javatutorial

Javanese Questions
Javanese Questions
109 участник(ов)

Чат предназначен для обмена знаниями строго в формате в вопрос-ответ. Тема — Java, Kotlin и Android. Вопрос должен быть предварительно прогуглен, понятно и грамотно сформулирован, помечен хэштегами. Ответ — тем более. Куски кода размером в несколько строк можно писать прямо здесь, для больших кусков кода стоит использовать http://gist.github.com/, http://pastebin.com/, https://codeshare.io/ или любой аналогичный сервис. В некоторых случаях можно прикреплять скриншоты. Стикеры и гифки запрещены. Дополнять и уточнять вопросы и ответы — редактированием исходного сообщения. Обсуждения должны приводить к редактированию вопроса/ответа и удаляться. По хештегам можно искать существующие вопросы и овтеты: #вопрос #ответ #git #generics #java #server #awt #javafx #swing #kotlin #anko #tornadofx #ktor #android #recyclerView #performance #arch #network #permissions #storage #async