2012-04-06 41 views
4

我正在編寫一個程序來偵聽系統剪貼板中的更改。偵聽器在單獨的線程上運行,並在剪貼板的內容發生更改時執行一些操作(例如寫入文件)。Java線程在沒有專注於OSX時進入睡眠狀態

我在使用ClipboardOwner interface輪詢剪貼板,以便當我的程序失去剪貼板的所有權(意味着另一個進程修改了剪貼板)時,在我的程序中觸發一個事件讓我讀取更改。

public class OwnershipClipboardListener extends Thread implements ClipboardOwner 
{ 
    private Clipboard clipB = Toolkit.getDefaultToolkit().getSystemClipboard(); 

    public void run() 
    { 
     /* Initialize ClipboardListener and gain ownership of clipboard */ 
    } 

    @Override 
    public void lostOwnership(Clipboard clipboard, Transferable transferable) 
    { 
     /* Auto-fired when I lose Clipboard ownership. 
      Can do processing and regaining ownership here */ 
    }  
} 

的問題是,在OSX上運行時,到剪貼板的任何變化被反映僅如果我手動Cmd的-Tab鍵以在船塢內的正在運行的進程圖標。因此,如果在切換到停靠欄圖標之前存在多個剪貼板操作,則只有最後一個纔有效。我不在Linux或Windows上面對這個問題。

這就像線程在程序失去焦點時進入睡眠狀態,但最後一個事件觸發器在喚醒時仍然會觸發。有什麼辦法可以預防這種睡眠嗎?

+0

帖子[這](HTTP:// stackoverflow.com/questions/4402001/cant-copy-to-a-clipboard-from-a-background-java-application-on-mac-osx「)和[this](http://stackoverflow.com/questions/ 7717824/cant-monitor-system-clipboard-changes-from-a-background-java-application-on-mac)請參閱m有類似的問題,但在大多數情況下,他們的剪貼板是做數據傳輸的一種解決方法。我實際上需要一直在閱讀剪貼板。 – 2012-04-06 04:58:38

回答

1

我懷疑OSX沒有提供剪貼板更改的通知,所以當Java由於某種其他原因而被喚醒時,Java會盡可能地做出最好的通知。

我的懷疑來自NSPasteboard文檔,特別是changeCount例程。它說:「因此,您可以在獲取紙板所有權時記錄更改計數,並將其與changeCount返回的值進行比較,以確定您是否仍擁有所有權。」沒有提及使用事件來檢測更改。

+0

但是在這種情況下,lostOwnership()方法的確被解僱了,除非它只在將焦點更改爲Java應用程序時纔會發生。在其他系統上,即使在後臺也會觸發事件。 – 2012-04-09 08:07:00

+0

我的意思是操作系統不會通知JVM發生更改。 JVM顯然會檢查changeCount,但只有當它得到一些週期時,比如當它的某個窗口獲得焦點時。 – 2012-04-09 18:25:32

0

似乎基思是對的。但是,您可以通過發送應用背景(在* nix)做一個變通方法:

java -jar clipboard-1.0.jar & 

這將打開在後臺的Java應用程序,不需要窗口焦點通知解僱。

0

我正試圖使用​​這種解決方法,但它不會爲我,想法做詭計嗎? 注意,現在沒有在java中的Mac OS X端口的錯誤:http://java.net/jira/browse/MACOSX_PORT-511

這是我的源代碼:


import java.awt.Toolkit; 
import java.awt.datatransfer.*; 
import java.io.IOException; 

public class ClipboardListener extends Thread implements ClipboardOwner { 

    Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 

    public void run(){ 
     Transferable selection = systemClipboard.getContents(this); 
     gainOwnership(selection); 
     while (true) {} 
    } 

    public void gainOwnership(Transferable t){ 
     try {this.sleep(100);} 
     catch (InterruptedException e) {} 
     systemClipboard.setContents(t, this); 
    } 

    public void lostOwnership(Clipboard clipboard, Transferable contents) { 
     try {System.out.println((String) clipboard.getData(DataFlavor.stringFlavor));} 
     catch (UnsupportedFlavorException e) {} 
     catch (IOException e) {} 
     gainOwnership(contents); 
    } 
} 

public class myApp { 

    public static void main(String[] args){ 
     ClipboardListener listener = new ClipboardListener(); 
     listener.start();} 
} 
相關問題