问题
I have a Tkinter GUI application that I need to hide on a buttonpress. I cannot assume that the application will have focus, so I implemented pyHook, keylogger-style. However, whenever I call withdraw() from a function launched by pyHook, the window hangs and I have to force-close it.
To test, I added a button inside the GUI itself to call exactly the same function, and it works just fine. What's going on? 'hiding' prints both times, so I know it is really hanging on the withdraw() call itself.
Below is a minimal complete verifiable example to demonstrate what I mean:
from Tkinter import *
import threading
import time
try:
import pythoncom, pyHook
except ImportError:
print 'The pythoncom or pyHook modules are not installed.'
# main gui box
class TestingGUI:
def __init__(self, root):
self.root = root
self.root.title('TestingGUI')
self.button = Button(root, text="Withdraw", command=self.Hide) # works fine
self.button.grid()
def ButtonPress(self, scancode, ascii):
if scancode == 82: # kp_0
self.Hide() # hangs
def Hide(self):
print 'hiding'
self.root.withdraw()
time.sleep(2)
self.root.deiconify()
root = Tk()
TestingGUI = TestingGUI(root)
def keypressed(event):
key = chr(event.Ascii)
# have to start thread in order to return True as required by pyHook
threading.Thread(target=TestingGUI.ButtonPress, args=(event.ScanCode,key)).start()
return True
def startlogger():
obj = pyHook.HookManager()
obj.KeyDown = keypressed
obj.HookKeyboard()
pythoncom.PumpMessages()
# need this to run at the same time
logger = threading.Thread(target=startlogger)
# quits on main program exit
logger.daemon = True
logger.start()
# main gui loop
root.mainloop()
回答1:
Solved as per this answer here:
Essentially, the function inside the Tkinter class responsible for dealing with keypresses, ButtonPress
, cannot be called from another thread.
来源:https://stackoverflow.com/questions/37909046/tkinter-withdraw-oddness-with-pyhook