使用tkinter监控剪贴板,我的代码有什么问题?

2024-09-28 17:20:02 发布

您现在位置:Python中文网/ 问答频道 /正文

关于代码的一些描述:

  1. 这是我程序的一部分,我只把相关的行放在这里
  2. 我希望这些代码能做的,就是监视剪贴板。如果我收到“http:xxx“在我的剪贴板上,它显示一个弹出窗口窗口。如果剪贴板的内容不变,窗口将不再显示
  3. 运行时,它可以正常弹出一次窗口,但当我从开始将另一个字符串复制到剪贴板时,它不会再次弹出窗口
  4. 我在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()

在编辑:A.罗达斯的代码有用。它似乎多线程导致问题。很深原因不明。在


Tags: 代码importselfmessageifosdefcontent
3条回答

我认为多线程不是适合您的最佳方法,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)

这个问题很有可能是因为使用从主线程以外的任何地方调用Tkinter函数的线程可能会导致问题。在

使用线程而不是利用内置的无限循环(事件循环)有什么原因?我建议使用after每隔一秒左右检查一下键盘。在

@laike9m
你的代码的错误是os.管道使用。
操作系统读取()是一个阻塞函数,它将接收操作系统读取()阻塞一次clipboard_confirm运行。导致用户界面卡住。
此错误与after和多线程无关。在

相关问题 更多 >