在剪贴板内容改变时触发事件
我想在我的Mac Lion上用Python脚本获取剪贴板的内容。
我在找一个事件或者类似的东西,因为如果我用循环的话,我的程序就会一直在盯着剪贴板,浪费很多时间。
有没有什么好主意?
4 个回答
1
简单!
import os
def macSetClipboard(text):
outf = os.popen('pbcopy', 'w')
outf.write(text)
outf.close()
def macGetClipboard():
outf = os.popen('pbpaste', 'r')
content = outf.read()
outf.close()
return content
current_clipboard = macGetClipboard()
while True:
clipboard = macGetClipboard()
if clipboard != current_clipboard:
print(clipboard)
macSetClipboard("my new string")
print(macGetClipboard())
break
2
在Macosx上,pyperclip
的核心内容是:
import os
def macSetClipboard(text):
outf = os.popen('pbcopy', 'w')
outf.write(text)
outf.close()
def macGetClipboard():
outf = os.popen('pbpaste', 'r')
content = outf.read()
outf.close()
return content
这些对我有效,你觉得怎么样?
我不太明白你说的在循环中是什么意思。
编辑 添加了一个糟糕的轮询示例,展示了每次copy
到剪贴板时,changeCount()
是如何增加的。不过这仍然不是提问者想要的,因为似乎没有事件或通知可以用来监测NSPasteboard
的修改。
from LaunchServices import *
from AppKit import *
import os
from threading import Timer
def poll_clipboard():
pasteboard = NSPasteboard.generalPasteboard()
print pasteboard.changeCount()
def main():
while True:
t = Timer(1, poll_clipboard)
t.start()
t.join()
if __name__ == "__main__":
main()
24
你有没有想过用一个无限循环,并在每次尝试之间“休眠”一下呢?我用过pyperclip这个库来做一个简单的演示,结果在Windows和Linux上都很好用。
import time
import sys
import os
import pyperclip
recent_value = ""
while True:
tmp_value = pyperclip.paste()
if tmp_value != recent_value:
recent_value = tmp_value
print("Value changed: %s" % str(recent_value)[:20])
time.sleep(0.1)
在这里,你可以用你想做的事情来替代print
。
下面是一个完整的多线程示例。
import time
import threading
import pyperclip
def is_url_but_not_bitly(url):
if url.startswith("http://") and not "bit.ly" in url:
return True
return False
def print_to_stdout(clipboard_content):
print ("Found url: %s" % str(clipboard_content))
class ClipboardWatcher(threading.Thread):
def __init__(self, predicate, callback, pause=5.):
super(ClipboardWatcher, self).__init__()
self._predicate = predicate
self._callback = callback
self._pause = pause
self._stopping = False
def run(self):
recent_value = ""
while not self._stopping:
tmp_value = pyperclip.paste()
if tmp_value != recent_value:
recent_value = tmp_value
if self._predicate(recent_value):
self._callback(recent_value)
time.sleep(self._pause)
def stop(self):
self._stopping = True
def main():
watcher = ClipboardWatcher(is_url_but_not_bitly,
print_to_stdout,
5.)
watcher.start()
while True:
try:
print("Waiting for changed clipboard...")
time.sleep(10)
except KeyboardInterrupt:
watcher.stop()
break
if __name__ == "__main__":
main()
我创建了一个线程的子类,重写了run
和__init__
这两个方法,然后创建了这个类的一个实例。通过调用watcher.start()
(而不是run()
!),你就可以启动这个线程。
为了安全地停止这个线程,我会等到按下
在这个类的初始化中,你还有一个pause
参数,可以用来控制每次尝试之间等待多久。
像我示例中那样使用ClipboardWatcher类,把回调函数替换成你想做的,比如lambda x: bitly(x, username, password)
。