2013-01-08 21 views
6

我正在嘗試製作一個應該顯示剪貼板內容的小桌面應用程序(如果它是一個字符串)。我已經完成了一個構造函數,它可以很好地工作,現在我只想在文本被複制到操作系統中的剪貼板時調用類似的方法。我很新,所以任何幫助將不勝感激!東西告訴我,我應該使用中斷以某種方式...當剪貼板的內容被改變時調用一個方法

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

回答

4

您可以撥打Clipboard.addFlavorListener監聽來自操作系統剪貼板更新:

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

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

一些旁註:

  • 要啓動您的應用程序,請考慮使用initial threads
  • 撥打JFrame.pack設置幀大小。
  • Key Bindings優於KeyListeners,用於在Swing中映射KeyEvents
+0

+1打我:P ... – MadProgrammer

+2

我不知道這真的對我的作品:從我的實驗,似乎偵聽器時(例如),我首先選擇和複製文本響應..但如果我再複製一些更多的文本,聽衆不會觸發。這並不奇怪,因爲看起來你正在等待FLAVOR改變。可能的解決辦法可能是在每次事件後清空剪貼板? –

+1

@mikerodent - 只要您使用不同的應用程序從剪貼板複製,事件就會觸發。只要你使用相同的應用程序,事件只會觸發一次。 – jamie

8

我用這個。全班同學

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) { 
    } 
} 

} 

當其他程序取得剪貼板的所有權時,它將等待250毫秒並收回剪貼板的所有權和更新的內容。

+0

什麼是BoardListener? – qed

+0

BoardListener是類名稱,我沒有注意到,當我將該類的名稱更改爲ClipBoardListener時,該類有實例。它應該是公共類BoardListener。 – daredesm

+0

這太棒了!它實際上工作。 – Yster

1

下面是一個SSCCE ...你可以運行它並選擇文本並按Ctrl-C多次...選擇的文本被打印出來。

正如你所看到的,它比Reimius的回答更有意義。實際上,您必須清除剪貼板(這很棘手!),以便風味監聽器每次複製一些新文本時作出響應。

此外,當清除剪貼板時,您可能需要抑制「味道變化」導致的輸出......儘管可能比我的解決方案更加靈活。

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++; 
     } 

    } 

}