2013-01-08 13 views
6

Sto cercando di fare un po 'un'applicazione desktop che dovrebbe mostrare il contenuto degli appunti (se si tratta di una stringa). Ho fatto un costruttore che lo fa e funziona bene, ora voglio solo effettuare una chiamata ad un metodo simile ogni volta che un testo viene copiato negli appunti nel sistema operativo. Sono abbastanza nuovo in questo modo qualsiasi aiuto sarebbe apprezzato! Qualcosa mi dice che dovrei usare gli interrupt in qualche modo ...chiamare un metodo quando il contenuto della clipboard è cambiato

package pasty; 

import java.awt.FlowLayout; 
import java.awt.Toolkit; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.UnsupportedFlavorException; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JTextField; 

public class PastyFrame implements KeyListener { 

    String currentClipboardString; 
    JLabel clipboardLabel = new JLabel(); 

    public PastyFrame() { 
     JFrame frame = new JFrame(); 
     frame.setVisible(true); 

     try { 
      currentClipboardString = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); 
     } catch (UnsupportedFlavorException | IOException ex) { 
      Logger.getLogger(PastyFrame.class.getName()).log(Level.SEVERE, null, ex); 

      currentClipboardString = ""; 
     } 
     if (currentClipboardString.isEmpty()) { 
      currentClipboardString = "The clipboard is empty"; 
     } 
     frame.setSize(400, 100); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setResizable(false); 
     frame.setLayout(new FlowLayout()); 


     clipboardLabel.setText(currentClipboardString); 
     frame.add(clipboardLabel); 
} 

risposta

4

È possibile chiamare Clipboard.addFlavorListener per ascoltare gli aggiornamenti degli appunti dal sistema operativo:

Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(new FlavorListener() { 
    @Override 
    public void flavorsChanged(FlavorEvent e) { 

     System.out.println("ClipBoard UPDATED: " + e.getSource() + " " + e.toString()); 
    } 
}); 

Alcune note a margine:

  • Per avviare l'applicazione, prendere in considerazione l'utilizzo di initial threads.
  • Chiamare JFrame.pack per impostare la dimensione del frame.
  • Key Bindings sono preferiti sopra KeyListeners per la mappatura KeyEvents in Swing.
+0

+1 mi ha battuto: P ... – MadProgrammer

+2

Non sono sicuro che questo funziona davvero per me: dai miei esperimenti sembra che l'ascoltatore risponde quando (per esempio) ho selezionare e copiare del testo .. ma se poi copio un altro testo l'ascoltatore non spara. Questo non è sorprendente in quanto sembra che stai aspettando che il FLAVOR cambi. Forse la soluzione potrebbe essere quella di svuotare gli appunti dopo ogni evento? –

+1

@mikerodent: l'evento si attiva finché si copia dagli Appunti con diverse app. Finché utilizzi la stessa app, l'evento scatterà solo una volta. – jamie

8

Io uso questo. L'intera classe.

public class ClipBoardListener extends Thread implements ClipboardOwner{ 
Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard(); 


    @Override 
    public void run() { 
    Transferable trans = sysClip.getContents(this); 
    TakeOwnership(trans);  

    } 

    @Override 
    public void lostOwnership(Clipboard c, Transferable t) { 

    try { 
    ClipBoardListener.sleep(250); //waiting e.g for loading huge elements like word's etc. 
    } catch(Exception e) { 
    System.out.println("Exception: " + e); 
    } 
    Transferable contents = sysClip.getContents(this); 
    try { 
     process_clipboard(contents, c); 
    } catch (Exception ex) { 
     Logger.getLogger(ClipBoardListener.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    TakeOwnership(contents); 


} 

    void TakeOwnership(Transferable t) { 
    sysClip.setContents(t, this); 
    } 

public void process_clipboard(Transferable t, Clipboard c) { //your implementation 
    String tempText; 
    Transferable trans = t; 

    try { 
     if (trans != null?trans.isDataFlavorSupported(DataFlavor.stringFlavor):false) { 
      tempText = (String) trans.getTransferData(DataFlavor.stringFlavor); 
      System.out.println(tempText); 
     } 

    } catch (Exception e) { 
    } 
} 

} 

Quando altro programma assume la proprietà della clipboard attende 250 ms e riprende possesso di appunti con contenuti aggiornati.

+0

cos'è 'BoardListener'? – qed

+0

BoardListener è un nome di classe, non ho notato che quando stavo cambiando il nome della classe in ClipBoardListener ci sono istanze di questa classe. Dovrebbe essere invece BoardListener di classe pubblica. – daredesm

+0

Questo è fantastico! Funziona davvero. – Yster

1

seguito è riportato uno SSCCE ... è possibile eseguirlo e selezionare il testo e andare Ctrl-C, più volte ... il testo selezionato ottiene stampati.

Come potete vedere si tratta di un po 'più complessa di risposta Reimius'. Devi infatti cancellare gli appunti (che è difficile!) Affinché l'ascoltatore di sapori risponda ogni volta che copi del nuovo testo.

Inoltre è probabilmente necessario per sopprimere l'uscita causata dal "cambiamento sapore" quando si cancella la clipboard ... anche se ci può essere una soluzione più intelligente di me.

public class ClipboardListenerTest { 

    public static void main(String[] args) throws InvocationTargetException, InterruptedException { 

     SwingUtilities.invokeAndWait(new Runnable() { 
      public void run() { 
       final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 
       clipboard.addFlavorListener(new FlavorListener() { 
        // this is needed to prevent output when you clear the clipboard 
        boolean suppressOutput = false; 

        // this is a specially devised Transferable - sole purpose to clear the clipboard 
        Transferable clearingTransferable = new Transferable() { 
         public DataFlavor[] getTransferDataFlavors() { 
          return new DataFlavor[0]; 
         } 
         public boolean isDataFlavorSupported(DataFlavor flavor) { 
          return false; 
         } 
         public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { 
          throw new UnsupportedFlavorException(flavor); 
         } 
        }; 

        @Override 
        public void flavorsChanged(FlavorEvent e) { 
         Transferable contentsTransferable = clipboard.getContents(null); 
         // NB the Transferable returned from getContents is NEVER the same as the 
         // clearing Transferable! 

         if (!suppressOutput) { 
          System.out.println(String.format("# clipboard UPDATED, src %s, string %s, clearingT? %b", e.getSource(), e.toString(), 
            contentsTransferable == clearingTransferable)); 
          try { 
           String stringData = (String)clipboard.getData(DataFlavor.stringFlavor); 
           System.out.println(String.format("# string data |%s|", stringData)); 
          } catch (UnsupportedFlavorException | IOException e1) { 
           // TODO Auto-generated catch block 
           e1.printStackTrace(); 
          } 
         } 

         else { 
          // my experiments seem to show that you have to spawn a new Runnable if you want 
          // to leave suppressOutput long enough for it to prevent the "CLEAR" operation 
          // producing output... 
          SwingUtilities.invokeLater(new Runnable() { 
           @Override 
           public void run() { 
            suppressOutput = false; 
           } 
          }); 

         } 
         suppressOutput = true; 
         clipboard.setContents(clearingTransferable, null); 
        } 
       }); 

      } 

     }); 

     int i = 0; 
     while (i < 100) { 
      Thread.sleep(500L); 
      System.out.println("# pibble"); 
      i++; 
     } 

    } 

} 
Problemi correlati