1

ボタンを押すと非表示にする必要がある Tkinter GUI アプリケーションがあります。アプリケーションにフォーカスがあるとは想定できないため、キーロガー スタイルの pyHook を実装しました。ただし、pyHook によって起動された関数から draw() を呼び出すたびに、ウィンドウがハングし、強制的に閉じる必要があります。

テストするために、GUI 自体の中にボタンを追加して、まったく同じ関数を呼び出したところ、問題なく動作しました。どうしたの?「hiding」は両方とも出力されるため、実際にはwithdraw()呼び出し自体にかかっていることがわかります。

以下は、私が何を意味するかを示すための最小限の完全な検証可能な例です。

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()
4

1 に答える 1

1

こちらの回答に従って解決しました:

基本的に、キー押下の処理を担当する Tkinter クラス内の関数 はButtonPress、別のスレッドから呼び出すことはできません。

于 2016-06-21T13:17:54.830 に答える