Текстовая запись Tkinter с pyHook висит в графическом интерфейсе

У меня есть приложение TKinter GUI, в которое мне нужно ввести текст. Я не могу предположить, что приложение будет иметь фокус, поэтому я реализовал pyHook, keylogger-style.

Когда окно GUI не имеет фокуса, текстовая запись работает очень хорошо, и обновления StringVar корректно отображаются. Когда окно GUI имеет фокус, и я пытаюсь ввести текст, все происходит сбой.

т.е., если я нажму кнопку консоли или что-нибудь еще после запуска программы, будет работать текстовая запись. Если я сразу же попробую ввести текст (графический интерфейс начнется с фокуса), или я переориентирую окно в любой момент и введите текст, он сработает.

Что происходит?

Ниже приведен минимальный полный проверенный пример, чтобы продемонстрировать, что я имею в виду:

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.search = StringVar() self.searchbox = Label(root, textvariable=self.search) self.searchbox.grid() def ButtonPress(self, scancode, ascii): self.search.set(ascii) root = Tk() TestingGUI = TestingGUI(root) def keypressed(event): key = chr(event.Ascii) 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() 

One Solution collect form web for “Текстовая запись Tkinter с pyHook висит в графическом интерфейсе”

Я изменил исходный код, заданный в вопросе (и другой), так что функция обратного вызова, связанная с pyHook, отправляет данные о событиях, связанных с клавиатурой, в очередь. То, как объект GUI уведомляется о событии, может выглядеть бесполезно сложным. Попытка вызвать root.event_generate в root.event_generate казалось, зависла. Также set метод threading.Event казалось, вызывал проблемы при вызове в keypressed .

Контекст, в котором вызывается keypressed , вероятно, заложено.

 from Tkinter import * import threading import pythoncom, pyHook from multiprocessing import Pipe import Queue import functools class TestingGUI: def __init__(self, root, queue, quitfun): self.root = root self.root.title('TestingGUI') self.queue = queue self.quitfun = quitfun self.button = Button(root, text="Withdraw", command=self.hide) self.button.grid() self.search = StringVar() self.searchbox = Label(root, textvariable=self.search) self.searchbox.grid() self.root.bind('<<pyHookKeyDown>>', self.on_pyhook) self.root.protocol("WM_DELETE_WINDOW", self.on_quit) self.hiding = False def hide(self): if not self.hiding: print 'hiding' self.root.withdraw() # instead of time.sleep + self.root.deiconify() self.root.after(2000, self.unhide) self.hiding = True def unhide(self): self.root.deiconify() self.hiding = False def on_quit(self): self.quitfun() self.root.destroy() def on_pyhook(self, event): if not queue.empty(): scancode, ascii = queue.get() print scancode, ascii if scancode == 82: self.hide() self.search.set(ascii) root = Tk() pread, pwrite = Pipe(duplex=False) queue = Queue.Queue() def quitfun(): pwrite.send('quit') TestingGUI = TestingGUI(root, queue, quitfun) def hook_loop(root, pipe): while 1: msg = pipe.recv() if type(msg) is str and msg == 'quit': print 'exiting hook_loop' break root.event_generate('<<pyHookKeyDown>>', when='tail') # functools.partial puts arguments in this order def keypressed(pipe, queue, event): queue.put((event.ScanCode, chr(event.Ascii))) pipe.send(1) return True t = threading.Thread(target=hook_loop, args=(root, pread)) t.start() hm = pyHook.HookManager() hm.HookKeyboard() hm.KeyDown = functools.partial(keypressed, pwrite, queue) try: root.mainloop() except KeyboardInterrupt: quit_event.set() 
Python - лучший язык программирования в мире.