关于代码的一些描述:
after
方法中尝试了一些不同的区间值,结果相同。代码:
from tkinter import *
import os
import tkinter.messagebox as messagebox
import threading
import re
def watch_clipboard(tk,pipeout):
content = ''
last_content = ''
while True:
try:
content = tk.clipboard_get()
except TclError:
pass
result = re.match('http:',content)
if content != last_content:
if result:
last_content = content
message = 'show'.encode()
os.write(pipeout,message)
class GUI:
def __init__(self):
self.tk = Tk()
self.tk.resizable(0, 0)
self.tk.title('watch clipboard')
pipein,pipeout = os.pipe()
threading.Thread(target=watch_clipboard,daemon=True,args=(self.tk,pipeout)).start()
self.tk.after(5000,lambda:self.clipboard_confirm(pipein))
self.tk.mainloop()
def clipboard_confirm(self,pipein):
message = os.read(pipein,16)
if message == b'show':
self.tk.clipboard_clear()
messagebox.askokcancel('', 'add this in?', default='ok')
self.tk.after(5000,clipboard_confirm(pipein)) #add this
if __name__ == '__main__':
gui = GUI()
编辑:甲。罗达斯的代码有效。似乎多线程导致问题。深层原因仍然未知。
答案 0 :(得分:1)
我认为多线程不适合您的情况,而after
可能就足够了。您可以使用较低的超时时间调用tk.after
,而不是繁忙的等待循环。然后你只需要将watch_clipboard
的逻辑移到你的班级,这样你就不用担心线程之间的通信了。
class GUI:
def __init__(self):
self.tk = Tk()
self.tk.resizable(0, 0)
self.tk.title('watch clipboard')
self.last_content = ''
self.tk.after(100, self.watch_clipboard)
self.tk.mainloop()
def watch_clipboard(self):
try:
content = self.tk.clipboard_get()
if content != self.last_content and content.startswith('http:'):
self.last_content = content
self.tk.clipboard_clear()
messagebox.askokcancel('', 'add this in?', default='ok')
except TclError:
pass
self.tk.after(100, self.watch_clipboard)
答案 1 :(得分:1)
@ laike9m
您的代码错误是使用了os.pipe。
Os.read()是一个阻塞函数,一旦运行clipboard_confirm
,它将接收os.read()阻塞。导致UI卡住。
此错误与after
和多线程无关。
答案 2 :(得分:0)
问题很可能与使用线程有关 - 从主线程以外的任何地方调用Tkinter函数都可能导致问题。
你是否有理由使用线程而不是利用内置的无限循环(事件循环)?我建议每隔一秒钟使用after
来检查键盘。