我的程序有问题。当我启动程序并按任意键时,它将打印“ Sucfully”。如果我单击按钮再启动一次,然后按任意键,它将打印“ Sucfully” 2x,依此类推。 3x 4x 5x ..如何解决此问题?如果我使用join(),我的程序将崩溃。
并且,由于没有stop()选项,如何停止监听器?
from pynput.keyboard import Listener
from tkinter import *
import threading
from functools import partial
app = Tk()
def press(key):
keyd = str(key)
keyd = keyd.replace("Key.space", " ")
keyd = keyd.replace("'", "")
with open("doc.docx", "a") as o:
o.write(keyd)
print("Succefuly")
def startListener(arg):
if arg == btStart:
def subLis():
with Listener(on_press=press) as l:
l.join()
thr = threading.Thread(target=subLis)
thr.start()
btStart = Button(app, text="Start")
btStart.pack(side=TOP, fill=X)
btStart["command"] = partial(startListener, btStart)
btStop = Button(app, text="Stop")
btStop.pack(side=TOP, fill=X)
btStop["command"] = partial(startListener, btStop)
app.geometry("300x100+900+400")
app.mainloop()
答案 0 :(得分:0)
如果将线程保留在全局变量中,则可以检查它是否存在并且不创建第二个线程。
目前,我只知道一种停止线程的方法-使用某种组合键在return False
中执行press
。它将停止Listener
并结束线程。在代码键ESC
中停止线程。
from pynput.keyboard import Listener, Key
from tkinter import *
import threading
from functools import partial
def press(key):
keyd = str(key)
keyd = keyd.replace("Key.space", " ")
keyd = keyd.replace("'", "")
with open("doc.docx", "a") as o:
o.write(keyd)
print("Succefuly", keyd)
# stop Listener (and end thread)
if key == Key.esc:
return False
def subLis():
with Listener(on_press=press) as l:
l.join()
def startListener(arg):
global thr # inform function to use external variable
if arg == btStart:
if thr is None:
thr = threading.Thread(target=subLis)
thr.start()
else:
print('already running')
if arg == btStop:
if thr is None:
print('not running')
else:
print('TODO: stop thread')
#thr = None
# ---------------------------------------------------------
thr = None
app = Tk()
app.geometry("300x100+900+400")
btStart = Button(app, text="Start")
btStart.pack(side=TOP, fill=X)
btStart["command"] = partial(startListener, btStart)
btStop = Button(app, text="Stop")
btStop.pack(side=TOP, fill=X)
btStop["command"] = partial(startListener, btStop)
app.mainloop()
编辑:我在文档中发现Listener
来自Thread
,因此您可以使用与Thread
相同的方式
thr = Listener(...)
thr.start()
有函数Listener.stop()
停止监听器。对于此代码,它将是
thr.stop()
新代码
from pynput.keyboard import Listener, Key
from tkinter import *
from functools import partial
def press(key):
keyd = str(key)
keyd = keyd.replace("Key.space", " ")
keyd = keyd.replace("'", "")
with open("doc.docx", "a") as o:
o.write(keyd)
print("key:", keyd)
# key combination to stop listener (and end thread)
#if key == Key.esc:
# return False
def startListener(arg):
global thr # inform function to use external variable
if arg == btStart:
if thr is None:
print('[+] starting listener')
thr = Listener(on_press=press)
thr.start()
else:
print('[!] already running')
if arg == btStop:
if thr is None:
print('[!] not running')
else:
print('[+] stoping thread')
thr.stop()
thr.join()
thr = None
# ---------------------------------------------------------
thr = None
app = Tk()
app.geometry("300x100+900+400")
btStart = Button(app, text="Start")
btStart.pack(side=TOP, fill=X)
btStart["command"] = partial(startListener, btStart)
btStop = Button(app, text="Stop")
btStop.pack(side=TOP, fill=X)
btStop["command"] = partial(startListener, btStop)
app.mainloop()