Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Tkinter如何与听众一起工作?_Python_Python 3.x_Multithreading_Tkinter_Pynput - Fatal编程技术网

Python Tkinter如何与听众一起工作?

Python Tkinter如何与听众一起工作?,python,python-3.x,multithreading,tkinter,pynput,Python,Python 3.x,Multithreading,Tkinter,Pynput,我已经写了一个Tkinter,我希望有一个监听器来监视用户的键盘输入。但是,当我使用mainloop()启动Tkinter时,侦听器无法与它一起工作,并且将在我退出Tkinter之前启动 我曾尝试在Tkinter子单元中添加此侦听器,但效果不一样 def initialization(): print("Starting...") print("Start listener...") with mouse.Listener(on_click=onMouseClick) a

我已经写了一个Tkinter,我希望有一个监听器来监视用户的键盘输入。但是,当我使用
mainloop()
启动Tkinter时,侦听器无法与它一起工作,并且将在我退出Tkinter之前启动

我曾尝试在Tkinter子单元中添加此侦听器,但效果不一样

def initialization():
    print("Starting...")
    print("Start listener...")
    with mouse.Listener(on_click=onMouseClick) as listener:
        listener.join()

if __name__ == "__main__" :
    root = tk.Tk()
    root.geometry('800x80')
    root.resizable(height=True, width=True)
    root.overrideredirect(False)
    root.title('vENC Console')

    OneBtn = Button(root, command=initialization, text="One Button", width='30')
    root.mainloop()

我怎样才能让他们一起工作?我需要使用多线程吗?

与几乎所有GUI工具包一样,Tkinter是事件驱动的。这意味着Tkinter应该处理鼠标和键盘事件。 小部件可以通过添加特定事件的绑定来注册他们对事件感兴趣。Tkinter取决于事件的流程

本质上,
mainloop
等待事件发生(键盘、鼠标、超时),然后调用任何已注册的回调

添加另一个独立于Tkinter的事件处理程序将发生冲突。最重要的是,Tkinter不是线程安全的。如果必须使用线程,则应确保只有主线程使用Tkinter函数和方法

基本上,Tkinter和听者不能一起工作

因此,我建议您使用
bind\u all

通过使用
bind\u all
方法(阅读相关内容),您可以在应用程序级别注册绑定,而不是为特定的小部件注册绑定。

您可以这样编写绑定

listener = mouse.Listener(on_click=onMouseClick)
listener.start() # start thread

root.mainloop()

listener.stop()  # stop thread
listener.join()  # wait till thread really ends its job
不要在鼠标单击中使用
returnfalse
,因为它结束了监听器

tkinter
有自己的方法来获取键和鼠标事件,所以也许你应该使用它们<当tkinter的窗口最小化且无法从系统获取事件时,如果您必须捕获事件,则代码>侦听器将非常有用


编辑:

import tkinter as tk
from pynput import mouse

def onMouseClick(*args):
    print(args)

root = tk.Tk()

listener = mouse.Listener(on_click=onMouseClick)
listener.start() # start thread

root.mainloop()

listener.stop()  # stop thread
listener.join()  # wait till thread really ends its job

编辑:

import tkinter as tk
from pynput import mouse

def onMouseClick(*args):
    print(args)

def initialization():
    global listener

    print("Starting...")
    print("Start listener...")
    listener = mouse.Listener(on_click=onMouseClick)
    listener.start() # start thread

if __name__ == "__main__" :

    listener = None   

    root = tk.Tk()

    btn = tk.Button(root, command=initialization, text="One Button")
    btn.pack()

    root.mainloop()

    # stop listener if it was created
    if listener: # if listener is not None:
        print("Stop listener...")
        listener.stop()  # stop thread
        listener.join()  # wait till thread really ends its job

编辑:带有停止侦听器按钮的示例

import tkinter as tk
from pynput import mouse

def onMouseClick(*args):
    print(args)

def on_start():
    global listener

    if not listener:
        print("Start listener...")
        listener = mouse.Listener(on_click=onMouseClick)
        listener.start() # start thread
    else:
        print("listener already running")

def on_stop():
    global listener

    if listener:
        print("Stop listener...")
        listener.stop()  # stop thread
        listener.join()  # wait till thread really ends its job
        listener = None  # to inform that listener doesn't exist
    else:
        print("listener not running")

if __name__ == "__main__" :

    print("Starting...")

    listener = None  # to keep listener

    root = tk.Tk()

    btn = tk.Button(root, command=on_start, text="Star Mouse Listener")
    btn.pack()

    btn = tk.Button(root, command=on_stop, text="Stop Mouse Listener")
    btn.pack()

    root.mainloop()

    # stop listener if it was created
    if listener: # if listener is not None:
        print("Stop listener...")
        listener.stop()  # stop thread
        listener.join()  # wait till thread really ends its job

当用户关注或不关注tkinter时,你是否试图监视鼠标点击?@HenryYik事实上,我想监视键盘输入,例如,当用户发送键F5时,我将在tkinter中执行一些操作。他们的网站上有一个非阻塞解决方案
listener=mouse.listener(…)
然后
listener.start()
。我尝试使用Thread.start和Join,但效果不同。鼠标侦听器是一个threading.Thread,因此如果调用
listen.Join()
它将等待线程终止,从而阻塞tkinter的主线程。我不确定什么不起作用-你能澄清一下吗?它起作用了!但是为什么
mainloop()
必须介于
listener.start()
listener.join()之间呢?我可以先使用
mainloop
,然后启动Listener,然后使用Join()?
mailoop()
一直工作,直到您关闭窗口-所以
mainloop()
之后的Listener将在您关闭窗口后创建。所以,当我使用“Listener.start()”然后使用“mainloop()”启动Listener时,mainloop不会杀死Listener?仅块侦听器?然后join()将让它们一起工作?侦听器创建单独的线程来运行它-因此
mainloop()
不会阻止它,也不会杀死它。它们同时工作,但线程不同。而
join()
仅用于等待侦听器关闭(线程关闭)。您甚至可以跳过
join()
,但随后可能会出现错误,即线程未正确关闭(或类似情况)。是的,我删除了join(),然后重试。当我杀死“mainloop()”时,侦听器将同时被杀死。谢谢!它帮助我更深入地理解线程!