8

同じアプリケーションの異なるインスタンス間でオブジェクトのコピーアンドペーストを実装しようとしています。現在、1つのアプリケーションでのみ機能します(つまり、アプリケーションの同じインスタンスでコピーアンドペーストします)が、異なるインスタンス間では機能しません。

コードのコピー:

// MyObject is a class of objects I want to copy/paste;
// MyObjectSelection is a class that impements Transferable and ClipboardOwner interfaces

Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
MyObject data = new MyObject(selectedItems);
MyObjectSelection dataSelection = new MyObjectSelection(data);
clipboard.setContents(dataSelection, this);

その後、次のようにクリップボードの内容を確認できます。

Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable clipboardContent = clipboard.getContents(this);

DataFlavor[] flavors = clipboardContent.getTransferDataFlavors();
System.out.println("flavors.length=" + flavors.length);
for (int i = 0; i < flavors.length; i++){
   System.out.println("flavor=" + flavors[i]);
}

オブジェクトをコピーしたのと同じアプリケーションインスタンスからこれを行うと、機能します:flavors.lengthis 1、mimetype is application/x-java-serialized-object、そしてまあ、それは機能します。

しかし、アプリケーションを開いてコピーを実行し、同じアプリケーションを再度開いて(最初のアプリケーションは閉じられていない、つまり両方のインスタンスが同時に実行されている)、そこからクリップボードの内容を確認しようとすると、flavors.lengthです0

ドキュメントとこれらの例を調べました:1、2 しかし私はまだ私の実装で何が悪いのかを見つけることができません。

私は何か見落としてますか?


UPD: sscce:clipboard_test.zipを追加しました。

これは、3つのソースファイルを使用したテストアプリケーションです(私はEclipseを使用してビルドします)。

  • ClipboardTest.java -メインアプリクラス
  • MyObject.java -コピー/貼り付けするオブジェクトのクラス(このクラスにはの配列のみが含まれますString
  • MyObjectSelection.java -実装TranserableおよびClipboardOwnerインターフェースするクラス

    「コピー」、「テスト」の2つのボタンがあります。

    「コピー」ボタンを押すと、MyObjectの新しいインスタンスが作成され、クリップボードに配置されます。

    「テスト」ボタンを押すと、クリップボードの内容がチェックされ、コンソールにエコーされます(サポートされているDataFlavorの数とそれぞれDataFlavor

    したがって、次の手順を繰り返します。

  • アプリケーションを起動します

  • 「コピー」ボタンを押す:"object copied"ログにメッセージが表示されます
  • 「テスト」ボタンを押します。クリップボードの内容が表示されます。

       flavors.length = 1
       flavor[0] = java.awt.datatransfer.DataFlavor[mimetype=application/x-java-serialized-object;representationclass=MyObject]
    
  • アプリケーションの別のインスタンスを開始します(最初のインスタンスを閉じないでください)

  • 「テスト」ボタンを押します。クリップボードが空であることがわかります。

       flavors.length = 0
    

何故ですか?


UPD2: sscceはここに直接投稿されました:

  import java.awt.BorderLayout;

  import java.awt.datatransfer.Clipboard;
  import java.awt.datatransfer.ClipboardOwner;
  import java.awt.datatransfer.DataFlavor;
  import java.awt.datatransfer.Transferable;
  import java.awt.datatransfer.UnsupportedFlavorException;

  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;

  import java.awt.Toolkit;

  import javax.swing.JButton;
  import javax.swing.SwingUtilities; 
  import javax.swing.JFrame;

  public final class ClipboardTest implements Runnable, ClipboardOwner {

     public static void main(String[] args) {
        SwingUtilities.invokeLater (new ClipboardTest());
     } 

     public void run() {

        JFrame f = new JFrame ("Clipboard test");
        f.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);

        //-- Create "copy" button.
        //   When you click it, new object "test_items" becomes created
        //   and put to the clipboard.
        {
           JButton button_copy = new JButton("copy");
           button_copy.addActionListener(new ActionListener(){
              public void actionPerformed(ActionEvent e){

                 String[] test_items = {
                    "one", "two", "three"
                 };

                 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                 MyObject data = new MyObject(test_items);
                 MyObjectSelection dataSelection = new MyObjectSelection(data);
                 clipboard.setContents(dataSelection, ClipboardTest.this);

                 System.out.println("object copied");
              }
           });
           f.add(button_copy, BorderLayout.NORTH);
        }

        //-- Create "test" button.
        //   When you click it, clipboard contents are checked
        //   and echoed to the console (count of supported DataFlavor's, and each DataFlavor)
        {
           JButton button_test = new JButton("test");
           button_test.addActionListener(new ActionListener(){
              public void actionPerformed(ActionEvent e){

                 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                 Transferable clipboardContent = clipboard.getContents(this);

                 DataFlavor[] flavors = clipboardContent.getTransferDataFlavors();
                 System.out.println("flavors.length = " + flavors.length);
                 for (int i = 0; i < flavors.length; i++){
                    System.out.println("flavor[" + i + "] = " + flavors[i]);
                 }

              }
           });
           f.add(button_test, BorderLayout.SOUTH);
        }

        f.pack();
        f.setVisible(true);
     }



     // ClipboardOwner implementation

     @Override
     public void lostOwnership(Clipboard clipboard, Transferable transferable){
        System.out.println("ClipboardTest: Lost ownership");
     }







     /* *****************************************************************************************
      * Object that I want to copy/paste
      * ****************************************************************************************/

     public static class MyObject {

        private String[] items;

        public MyObject(String[] items){
           this.setItems(items);
        }

        public String[] getItems(){
           return this.items;
        }

        public void setItems(String[] items){
           this.items = items;
        }

     }




     public static class MyObjectSelection implements Transferable, ClipboardOwner {

        private static DataFlavor dmselFlavor = new DataFlavor(MyObject.class, "Test data flavor");
        private MyObject selection;



        public MyObjectSelection(MyObject selection){
           this.selection = selection;
        }


        // Transferable implementation

        @Override
        public DataFlavor[] getTransferDataFlavors(){
           System.out.println("getTransferDataFlavors");
           DataFlavor[] ret = {dmselFlavor};
           return ret;
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor){
           return dmselFlavor.equals(flavor);
        }

        @Override
        public synchronized Object getTransferData (DataFlavor flavor)
           throws UnsupportedFlavorException 
        {
           if (isDataFlavorSupported(flavor)){
              return this.selection;
           } else {
              throw new UnsupportedFlavorException(dmselFlavor);
           }
        }



        // ClipboardOwner implementation

        @Override
        public void lostOwnership(Clipboard clipboard, Transferable transferable){
           System.out.println("MyObjectSelection: Lost ownership");
        }

     }

  }
4

1 に答える 1

7

このチュートリアルの引用:

このメカニズムを使用してデータを転送するにはObjectシリアル化を使用するため、データの転送に使用するクラスは、それを使用してSerializableシリアル化されるものと同様に、インターフェイスを実装する必要があります。すべてがシリアル化できない場合はNotSerializableException、クリップボードへのドロップまたはコピー中に表示されます。

あなたMyObjectはそうではないSerializableので、それは機能しません。フレームワークは明らかにこの事実を検出するため(シリアル化可能な親クラスのシリアル化不可能なサブクラスの状況、またはプロセスでのみ非シリアル化可能性が検出される同様のシナリオとは対照的に)、他のプロセスにそのフレーバーを提供することさえありません。

一般に、同じJavaアプリケーションの2つのインスタンスは同じアドレス空間を持たないため、単に互いのメモリにアクセスすることはできません。したがって、転送するものはすべてシリアル化する必要があります。

于 2013-01-11T12:36:33.280 に答える