web-dev-qa-db-ja.com

グローバルクリップボードへのコピーは、UbuntuのJavaでは機能しません

スタンドアロンアプリケーションの次のコードは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セキュリティの変更 の後でも機能するはずです。 JTextField内からCtrl + Cを使用してコピーし、他の場所に貼り付けると機能します。

最新のJava7(jdk1.7.0_10)とjdk1.6.0_33の両方でubuntu11.04で失敗しました。 動作するはずです 最新のJava7を搭載したWindows7およびJava6_37を搭載したmacosx10.6で期待どおりに動作します。また、それらのjavaでxubuntu 12.04を試しましたが、そこでは機能しません。これはlinux/ubuntuのバグですか?

関連する質問

25
Karussell

私は仕事でアプリケーションで同じ問題を抱えていました、そしてここに私が見つけた記事が理由と可能な解決策を説明しています。お役に立てば幸いです。

なぜそれが起こるのか

クリップボードの永続性は、Ubuntuやその他のX11ベースのオペレーティングシステムの多くのプログラムに影響を与えるバグです。これを修正するのは、Google Summer of Code2010プロジェクトです。ウィキペディアには、この問題の概要が記載されています。ユーザーとして修正したい場合は、Parcelliteまたは別のクリップボードマネージャーをインストールできます。プログラマーとして修正したい場合は、ClipboardManager仕様に準拠するようにプログラムを変更できます。

X-Window wiki

gnomeライブラリを使用 クリップボードのstoreメソッドを呼び出してこれを修正できます。これまでのところ、試してみる価値があると思われるのはそれだけです。 GTKでも同様のことが見られましたが、Eclipseのバグのみでした。

17

私はあなたのコードをdebianテスト(7.0)とopenjdk7u3で試しました。結果は同じですが、問題(解決策)を見つけたと思います。

クリップボードのコンテンツは、プロセスが存在する場合にのみ有効です。コードを次のように変更すると機能します。

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ステートメントは、使用可能なコンテンツがない場合にコードが例外をスローしないようにします。これは、コードを1回実行して、プロセスが終了した場合に発生します。
System.in.read()は、プロセスを存続させます。 Enterキーを押さなくても、別のアプリケーションに貼り付けることができ、期待どおりに「NOW」が表示されます。
このように、コードは毎回機能します。

お役に立てれば。

12
raffael

Q:次のようなことを試しましたか?

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

permission Java.awt.AWTPermission "accessClipboard";

参照:

4
paulsm4

ここでテストを表示できます。

TextArea(デフォルトのコピー/貼り付けアクションはubuntuの他のアプリですぐに機能します)

システムクリップボードとの間でコピーアンドペーストする2つのボタンを追加しました

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 があることを確認してください。これは、おそらく使用する必要があるものです(非推奨ですが)

私はUbuntu12.10でJava 1.4からJava 1.6までコードをテストしましたが、それを抽出したコードはubuntu9.0以降で使用されています。

1
albfan