2013-01-11 14 views
6

Ich versuche, Kopieren und Einfügen von Objekten zwischen verschiedenen Instanzen der gleichen Anwendung zu implementieren. Derzeit funktioniert es nur in einer Anwendung (ich meine, kopieren und einfügen in der gleichen Instanz der Anwendung), funktioniert aber nicht zwischen verschiedenen Instanzen.Java: Verwenden Sie die Zwischenablage zum Kopieren und Einfügen von Java-Objekten zwischen verschiedenen Instanzen der gleichen Anwendung

Kopieren Code:

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

Danach kann ich Inhalt der Zwischenablage überprüfen, wie folgt aus:

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

Wenn ich dies tun aus dem gleichen Anwendungsinstanz, die ich Objekt kopiert, es funktioniert: flavors.length ist 1, Mimetype ist application/x-java-serialized-object, und, nun, es funktioniert.

Aber wenn ich Anwendung öffnen, führen Sie Kopie, dann öffnen Sie die gleiche Anwendung erneut (zuerst ist nicht geschlossen, d. H. Beide Instanzen laufen gleichzeitig), und versuchen, Inhalt der Zwischenablage von dort zu überprüfen, dann flavors.length ist .

Ich untersuchte die Dokumente und diese Beispiele: one, two, aber ich kann immer noch nicht finden, was in meiner Implementierung falsch ist.

Habe ich etwas übersehen?


UPD: Ich habe sscce: clipboard_test.zip.

Diese Testanwendung ist (ich benutze Eclipse-es zu bauen) mit 3 Quelldateien:

  • ClipboardTest.java - Haupt App Klasse
  • MyObject.java - Klasse für Objekte zum Kopieren/Einfügen (enthält diese Klasse nur Array von String)
  • MyObjectSelection.java - Klasse, die Transerable und ClipboardOwner Schnittstellen

    Es implementiert sind tw o Tasten: "Kopieren", "Testen".

    Wenn Sie die Schaltfläche "Kopieren" drücken, wird eine neue Instanz von MyObject erstellt und in die Zwischenablage kopiert.

    Wenn Sie "Test" -Taste, der Inhalt der Zwischenablage geprüft und hallte in der Konsole drücken (Anzahl der unterstützten DataFlavor ‚s, und jeder DataFlavor)

    diese Schritte So replizieren:

  • starten Anwendung

  • Drücken Sie „Kopie“ -Taste: Sie werden "object copied" Meldung im Protokoll
  • Drücken Sie „test“ Taste sehen: Sie Zwischenablage Inhalte sehen :

    flavors.length = 1 
        flavor[0] = java.awt.datatransfer.DataFlavor[mimetype=application/x-java-serialized-object;representationclass=MyObject] 
    
  • eine weitere Instanz der Anwendung starten (Sie die man nicht schließen zuerst)

  • Drücken Sie "Test" -Taste: Sie werden sehen, dass die Zwischenablage leer ist:

    flavors.length = 0 
    

Warum ist das?


UPD2: sscce direkt hier gepostet:

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

    } 

    } 
+3

Für bessere Hilfe, früher, ein [SSCCE] (http://sscce.org/). –

+0

Das Betriebssystem und die Startup-Argumente/Konfiguration der JVM haben auch viel zu sagen beim Zugriff auf die globale Zwischenablage – tucuxi

+0

@AndrewThompson, ich habe es hinzugefügt, überprüfe meine aktualisierte Frage. –

Antwort

5

this tutorial Zitiert:

die Übertragung der Daten über diesen Mechanismus verwendet Object Serialisierung, so dass die Klasse, die Sie die Übertragung verwenden Daten müssen die Schnittstelle Serializable implementieren, ebenso wie alles, was damit serialisiert wird. Wenn alles nicht serialisierbar ist, wird beim Ablegen oder Kopieren in die Zwischenablage eine NotSerializableException angezeigt.

Ihre MyObject ist nicht Serializable, so kann es nicht funktionieren. Das Framework erkennt diese Tatsache offensichtlich (im Gegensatz zu einer Situation mit einer unserialisierbaren Unterklasse einer serialisierbaren Elternklasse oder ähnlichen Szenarios, in denen eine Nicht-Serialisierbarkeit nur im Prozess erkannt wird), so dass es diesen anderen Prozessen nicht einmal angeboten wird.

Im Allgemeinen haben zwei Instanzen derselben Java-Anwendung nicht denselben Adressraum, sodass sie nicht einfach auf den Speicher des jeweils anderen zugreifen können. Daher muss alles, was Sie übertragen, serialisiert werden.

+0

Vielen Dank. Leider kann ich keinen Link zu diesem Tutorial in der offiziellen 'DataFlavor'-Dokumentation finden: http://docs.oracle.com/javase/7/docs/api/java/awt/datatransfer/DataFlavor.html –

+0

@DmitryFrank: Diese Verbindung ist tot, ich habe gerade einen Fehlerbericht dafür eingereicht. Aber mit dem Titel war es ziemlich einfach, die Version zu finden, auf die ich verwiesen habe. – MvG