函数启动和停止线程?

时间:2019-07-07 20:21:42

标签: python tkinter

我的程序有问题。当我启动程序并按任意键时,它将打印“ 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()

1 个答案:

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