если вы сохраните поток в глобальной переменной, тогда вы можете проверить, существует ли он, и не создавать второй поток.
На данный момент я знаю только один способ остановить поток - использовать некоторую комбинацию клавиш для выполнения 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()