2013-01-11 12 views
6

Sto cercando di implementare il copia-incolla di oggetti tra diverse istanze della stessa applicazione. Attualmente funziona solo in un'applicazione (voglio dire, copia e incolla nella stessa istanza di applicazione), ma non funziona tra diverse istanze.Java: utilizzare gli appunti per copiare gli oggetti java tra diverse istanze della stessa applicazione

codice Copia:

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

Dopo di che, posso controllare il contenuto degli appunti, come quella:

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

Se faccio questo dalla stessa istanza di applicazione che ho copiato oggetto, funziona: flavors.length è 1, il mimetype è application/x-java-serialized-object e, beh, funziona.

Ma se apro un'applicazione, eseguire la copia, quindi aprire la stessa applicazione di nuovo (primo non è chiuso, cioè entrambe le istanze vengono eseguite simultaneamente), e cercare di controllare il contenuto degli appunti da lì, quindi flavors.length è 0.

Ho esaminato i documenti e questi esempi: one, two, ma ancora non riesce a trovare ciò che è sbagliato nella mia implementazione.

Mi sono perso qualcosa?


UPD: ho aggiunto sscce: clipboard_test.zip.

Questa è un'applicazione di test (io uso Eclipse per costruirlo) con i file 3 Fonte:

  • ClipboardTest.java - classe principale applicazione
  • MyObject.java - classe per gli oggetti da copiare/incollare (questa classe contiene semplicemente array di String)
  • MyObjectSelection.java - classe che implementa Transerable e ClipboardOwner interfacce

    ci sono tw o pulsanti: "copia", "prova".

    Quando si preme il pulsante "copia", la nuova istanza di MyObject viene creata e inserita negli Appunti.

    Quando si preme il pulsante "test", il contenuto degli appunti sono controllati ed eco alla console (conteggio delle supportati DataFlavor 's, e ogni DataFlavor)

    Quindi, replicare questi passaggi:

  • Inizio applicazione

  • Premere il pulsante "copia": vedrete "object copied" messaggio nel registro
  • Premere il tasto "test": vedrete il contenuto di appunti :

    flavors.length = 1 
        flavor[0] = java.awt.datatransfer.DataFlavor[mimetype=application/x-java-serialized-object;representationclass=MyObject] 
    
  • Avviare un'altra istanza dell'applicazione (non chiudere il primo)

  • tasto

    Premere il "test": vedrete che negli appunti è vuota:

    flavors.length = 0 
    

Perché è quello?


UPD2: sscce postato direttamente qui:

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

Per un aiuto migliore, pubblicare un [SSCCE] (http://sscce.org/). –

+0

Anche il sistema operativo e gli argomenti/la configurazione di avvio della JVM hanno molto da dire sull'accesso agli appunti globali – tucuxi

+0

@AndrewThompson, l'ho aggiunto, controlla la mia domanda aggiornata. –

risposta

5

Citando this tutorial:

Trasferimento dei dati utilizzando questo meccanismo utilizza Object serializzazione, quindi la classe si utilizza per trasferire il i dati devono implementare l'interfaccia Serializable, così come tutto ciò che viene serializzato con esso. Se tutto non è serializzabile, vedrai un NotSerializableException durante la caduta o la copia negli Appunti.

Il tuo MyObject non è Serializable, quindi non può funzionare. Il framework sembra rilevare questo fatto (al contrario di una situazione con una sottoclasse non serializzabile di una classe genitore serializzabile, o scenari simili in cui la non serializzabilità viene rilevata solo nel processo), quindi non offrirà nemmeno quel sapore agli altri processi.

In generale, due istanze della stessa applicazione java non avranno lo stesso spazio di indirizzamento, quindi non possono semplicemente accedere alla memoria dell'altra. Quindi tutto ciò che trasferisci deve essere serializzato.

+0

Grazie mille. Sfortunatamente, non riesco a trovare il collegamento a questo tutorial dalla documentazione ufficiale di 'DataFlavor': http://docs.oracle.com/javase/7/docs/api/java/awt/datatransfer/DataFlavor.html –

+0

@DmitryFrank: Quel collegamento è morto, ho appena archiviato un bug report per questo. Ma usando il titolo, è stato abbastanza facile trovare la versione a cui ho fatto riferimento. – MvG

Problemi correlati