【发布时间】:2018-07-17 15:27:46
【问题描述】:
from pythoncom import PumpWaitingMessages
import pyHook, threading
import tkinter as tk
threadsRun = 1
token = 0
def pas():
while threadsRun:
pass
def listen(startButton):
"""Listens for keystrokes"""
def OnKeyboardEvent(event):
"""A key was pressed"""
global threadsRun
if event.Key == "R":
startButton.config(relief=tk.RAISED, state=tk.NORMAL, text="Start")
threadsRun = 0
return True
hm = pyHook.HookManager()
hm.KeyDown = OnKeyboardEvent
hm.HookKeyboard()
while threadsRun:
PumpWaitingMessages()
else:
hm.UnhookKeyboard()
def simplegui():
def threadmaker():
"""Starts threads running listen() and pas()"""
startButton.config(relief=tk.SUNKEN, state=tk.DISABLED, text="r=stop listening")
global token, threadsRun
threadsRun = 1
token += 1
t1 = threading.Thread(target=pas, name='pas{}'.format(token))
t2 = threading.Thread(target=listen, args=(startButton,), name='listen{}'.format(token))
t1.start()
t2.start()
def destroy():
"""exit program"""
global threadsRun
threadsRun = 0
root.destroy()
startButton = tk.Button(root, text="Start", command=threadmaker, height=10, width=20)
startButton.grid(row=1, column=0)
quitButton = tk.Button(root, text="Quit", command=destroy, height=10, width=20)
quitButton.grid(row=1, column=1)
root = tk.Tk()
simplegui()
root.mainloop()
代码说明:simplegui() 创建两个线程运行 pas() 和 listen()
同时。
listen() 等待键盘按下(只有r 做任何事情:退出两个线程/函数)。 pas() 什么都不做,但需要重现错误。
问题描述:
单击开始后,按键盘上的任何按钮都会导致tkinter 停止响应。
大约 2/3 的时间 r 将按预期运行。
我正在使用 Spyder IDE (python 3.5)。
一些观察:
使用打印语句,程序将在崩溃前进入listen() 中的while threadsRun 循环,但没有到达OnKeyboardEvent() print 语句。
在按键之前可以等待很长时间,它可能会冻结。
按下启动后可以立即按下一个键,它可以按预期工作。
删除 t1 = ... 和 t1.start() 行允许程序无错误地运行。
或者,删除所有 tkinter 代码允许程序无错误地运行。
一次混合一堆键会冻结它。
如果我在while threadsRun 循环中放置一个打印语句,r 将很少工作。
我在其他帖子中读过,tkinter 不是线程安全的,并且要使用队列。但我不明白怎么做。我也认为可能还有其他问题,因为它有时会起作用。 https://www.reddit.com/r/learnpython/comments/1v5v3r/tkinter_uis_toplevel_freezes_on_windows_machine/
非常感谢您的阅读。
【问题讨论】:
-
感谢编辑和回答 R4PH43L。我无法实现类和队列,但它确实激励我学习好的类:)。我找到了这个线程:stackoverflow.com/questions/42101906/… 我能够在没有
pumpwaitingmessages()的情况下重建代码,所以它可能有两个消息泵(我假设mainloop()中有一个),这导致了锁定。我的新代码现在按预期工作。
标签: python multithreading tkinter pyhook