简体   繁体   English

使用tkinter来查看剪贴板,我的代码出了什么问题?

[英]Using tkinter to watch for clipboard,what's wrong with my code?

Some description about the code: 关于代码的一些描述:

  1. This is part of my program and I only put the related lines here 这是我的计划的一部分,我只在这里放置相关的行
  2. What I hope these code could do,is to watch for my clipboard.If I copy " http:xxx " to my clipboard,it shows a pop-up window.If the content of the clipboard doesn't change,the window won't show again 我希望这些代码可以做的是观察我的剪贴板。如果我将“ http:xxx ”复制到我的剪贴板,它会显示一个弹出窗口。如果剪贴板的内容没有改变,窗口就赢了t再次显示
  3. When running,it can pop up the window normally for one time,but won't do it again when I copy another string to clipboard starting with 'http: ' 在运行时,它可以正常弹出窗口一次,但是当我将另一个字符串复制到剪贴板时,不会再次执行此操作,以'http: '开头
  4. I've tried some different interval values in the after method,same result. 我在after方法中尝试了一些不同的区间值,结果相同。

Code: 码:

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()

EDIT:A. 编辑:一。 Rodas's code works.It seems that multithreading causes the problem.Deep reason remain unknown. Rodas的代码有效。似乎多线程导致问题。深层原因仍然未知。

I think multithreading isn't the best approach for your situation and after may be enough. 我认为多线程不是最适合您情况的方法, after可能就足够了。 Instead of a busy waiting loop, you can call tk.after with a lower timeout. 您可以使用较低的超时调用tk.after而不是繁忙的等待循环。 Then you just need to move the logic of watch_clipboard to your class, so you don't have to worry about the communication between the threads. 然后你只需要将watch_clipboard的逻辑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)

@laike9m @ laike9m
The error with your code is that os.pipe is used. 代码的错误是使用了os.pipe。
Os.read() is a blocking function that will receive os.read() blocking once clipboard_confirm is run. Os.read()是一个阻挡功能将接收os.read()一次阻断clipboard_confirm运行。 Causes the UI to get stuck. 导致UI卡住。
This bug has nothing to do with after and multithreading. 这个bug与after和多线程无关。

There's a good chance the problem is related to using threads -- calling Tkinter functions from anywhere other than the main thread can cause problems. 这个问题很可能与使用线程有关 - 从主线程以外的任何地方调用Tkinter函数都可能导致问题。

Is there a reason you're using a thread rather than takingbadvantage of the built-in infinite loop (the event loop)? 您是否有理由使用线程而不是利用内置无限循环(事件循环)? I would advise making use of after to check the keyboard every second or so. 我会建议利用的after检查键盘每秒左右。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM