I am a teacher. I teach math, but since education is facing human resources crisis, I have some additional duties. I teach kids a bit of programming, they do quite well. Now I’d like to make with them a snake game, but I have a problem achieving multithreading in my GUI app.
I found similar cases but no solutions. Like here: Using the keyboard to move the character in a maze and here: Tkinter.Tk() and threading
def on_press(key):
print('{0} pressed'.format(key))
def on_release(key):
if key == Key.esc:
return False
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
root = Tk()
root.mainloop()
I expected the window to run simultaneously with the listener. instead, my code listens to the keyboard and then (after I shoot the listener down) pops the window up. it reverses when I call the listener after calling the mainloop, then first the window appears and after I shoot it down the listener is starting to work.
Advertisement
Answer
You don’t need Listener in tkinter. You can use root.bind to assign function to events press and release.
from tkinter import *
def on_press(event):
#print('on_press: event:', event)
#print('on_press: keysym:', event.keysym)
print('{0} pressed'.format(event.keysym))
def on_release(event):
#print('on_release: event:', event)
#print('on_release: keysym:', event.keysym)
print('{0} release'.format(event.keysym))
if event.keysym == 'Escape':
print("exist program")
root.destroy()
root = Tk()
root.bind('<KeyPress>', on_press)
root.bind('<KeyRelease>', on_release)
root.mainloop()
You can also assign function to every key separatelly
from tkinter import *
def on_escape(event):
print("exist program")
root.destroy()
root = Tk()
root.bind('<Escape>', on_escape)
#root.bind('<KeyPress-Escape>', on_press_escape)
#root.bind('<KeyRelease-Escape>', on_release_escape)
root.mainloop()
Keysyms in Tcl/Tk documentation: https://www.tcl.tk/man/tcl8.4/TkCmd/keysyms.htm
BTW:
If you want to run tkinter and pynput at the same time then you have to do it before join()
with Listener(on_press=on_press, on_release=on_release) as listener:
root = Tk()
root.mainloop()
#listener.stop()
listener.join()
or
listener = Listener(on_press=on_press, on_release=on_release) listener.start() root = Tk() root.mainloop() #listener.stop() listener.join()