2016-06-19 9 views
1

Ich habe eine Tkinter GUI-Anwendung, die ich auf einer Schaltfläche drücken muss ausblenden. Ich kann nicht davon ausgehen, dass die Anwendung den Fokus haben wird, also habe ich pyHook, Keylogger-Stil implementiert. Wenn ich jedoch remove() von einer Funktion, die von pyHook gestartet wurde, aufrufen, hängt das Fenster und ich muss es zwangsweise schließen.Tkinter zurückziehen Oddness mit pyHook

Um zu testen, fügte ich eine Schaltfläche in der GUI selbst, um genau die gleiche Funktion aufzurufen, und es funktioniert gut. Was ist los? 'Verstecken' druckt beide Male, so dass ich weiß, dass es wirklich an dem Aufruf von remove() hängt.

Unten finden Sie ein minimales vollständiges nachprüfbares Beispiel zu zeigen, was ich meine:

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() 
+0

Threads und tkinter nicht gut mischen, siehe zum Beispiel http://StackOverflow.com/a/10556698/5781248 –

+0

Ich weiß, dass es Probleme gibt, aber Sie werden feststellen, dass 'mainloop()' * ist * läuft im Hauptthread. Außerdem funktioniert dieses ganze Projekt gut in Linux, wenn ich Xs Datensatzkontext verwende. Dies ist definitiv ein pyHook-Problem. – heidi

+1

'threading.Thread (target = TestingGUI.ButtonPress, args = (event.ScanCode, key)). Start()' in der Funktion 'keypressed' sieht aus wie es ein tk-Widget verursacht, das außerhalb des Hauptthreads ie' self.root aufgerufen wird. remove() 'und' self.root.deiconify() 'Aufrufe. –

Antwort

1

gelöst, wie sie per this answer here:

Wesentliches mit Drücken von Tasten die Funktion innerhalb der Tkinter Klasse verantwortlich für den Umgang, ButtonPress, kann nicht aus einem anderen Thread aufgerufen werden.