0

コードに関する説明:

  1. これは私のプログラムの一部であり、関連する行のみをここに配置します
  2. これらのコードでできることは、クリップボードを監視することです。「http:xxx」をクリップボードにコピーすると、ポップアップウィンドウが表示されます。クリップボードの内容が変更されない場合、ウィンドウは表示されません。もう一度表示する
  3. 実行中は、ウィンドウを1回だけ正常にポップアップできますが、「http:」で始まる別の文字列をクリップボードにコピーすると、再度ポップアップすることはありません。
  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。Rodasのコードは機能します。マルチスレッドが問題を引き起こしているようです。深い理由は不明のままです。

4

3 に答える 3

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)
于 2013-03-23T19:00:35.500 に答える
1

@ laike9m
コードのエラーは、os.pipeが使用されていることです。
Os.read()は、実行されるとos.read()ブロッキングを受け取るブロッキング関数ですclipboard_confirm。UIが動かなくなる原因になります。このバグはマルチスレッドと
は何の関係もありません。after

于 2019-02-16T13:22:11.273 に答える
0

問題がスレッドの使用に関連している可能性が高いです。メインスレッド以外の場所からTkinter関数を呼び出すと、問題が発生する可能性があります。

組み込みの無限ループ(イベントループ)を利用するのではなく、スレッドを使用している理由はありますか?after毎秒かそこらでキーボードをチェックすることを利用することをお勧めします。

于 2013-03-23T19:02:20.570 に答える