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()
Code description:
simplegui()
creates two threads to run
pas()
and
listen()
simultaneously.
listen()
waits for keyboard presses(only r
does anything: exits both threads/functions).
pas()
does nothing but is needed to reproduce bug.
Problem description:
After clicking start, pressing any button on the keyboard can cause tkinter
to stop responding.
~2/3rd of the time r
will behave as intended.
I'm using Spyder IDE (python 3.5).
Some observations:
Using print statements, the program will go into while threadsRun
loop, in listen()
, before the crash, but didn't reach OnKeyboardEvent()
print statement.
Can wait a long time before pressing a key and it may freeze.
Can press a key instantly after pressing start and it may function as intended.
Removing t1 = ...
and t1.start()
lines allows program to run bug free.
Alternatively, removing all tkinter
code allows program to run bug free.
Mashing a bunch of keys all at once freezes it.
If I place a print statement inside the while threadsRun
loop, r
will rarely work.
I've read in other posts, tkinter
is not thread safe, and to use a queue. But I don't understand how. I also think maybe something else is wrong because it works sometimes. https://www.reddit.com/r/learnpython/comments/1v5v3r/tkinter_uis_toplevel_freezes_on_windows_machine/
Thanks very much for reading.