首页 > 解决方案 > Python pynput - 捕获键 - 侦听器回调中未处理的异常 - 主线程不在主循环中

问题描述

我在这里有一个双胞胎问题,我试图与 TKinter 绑定。但我愿意使用 PYNPUT 如果这有助于我让我的功能更快地工作。

我已经用 pynput 研究了这个 Pyhon - “侦听器回调中的未处理异常” ,它帮助了一些,但我还没有克服这个错误。

使用 PYNPUT,我能够捕获键,并分支到一个函数,但随后它进入 threading.py 和 __init__py 并因此而崩溃:

E:\Python\Python36\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition with Anaconda plugin 2019.2.4\helpers\pydev\pydevd.py" --multiproc --qt-support=auto --client 127.0.0.1 --port 10281 --file E:/GitHub/NealWalters/game/game.py
pydev debugger: process 32480 is connecting

Connected to pydev debugger (build 192.7142.79)
verify playerCard1=Queen of Clubs verify playerCard2=Six of Hearts
on_press: key='p'
calling self.play()
Unhandled exception in listener callback
Traceback (most recent call last):
  File "E:\Python\Python36\lib\site-packages\pynput\_util\__init__.py", line 162, in inner
    return f(self, *args, **kwargs)
  File "E:\Python\Python36\lib\site-packages\pynput\keyboard\_win32.py", line 280, in _process
    self.on_press(key)
  File "E:\Python\Python36\lib\site-packages\pynput\_util\__init__.py", line 78, in inner
    if f(*args) is False:
  File "E:/GitHub/NealWalters/game/game.py", line 117, in on_press
    self.play()
  File "E:/GitHub/NealWalters/game/game.py", line 177, in play
    self.message1.setMsg() # clear
  File "E:\GitHub\NealWalters\game\textboxes.py", line 56, in setMsg
    self.msgLine.undraw( )
  File "E:\GitHub\NealWalters\game\graphics.py", line 68, in undraw
    self.canvas.delete(self.id)
  File "E:\Python\Python36\lib\tkinter\__init__.py", line 2508, in delete
    self.tk.call((self._w, 'delete') + args)
RuntimeError: main thread is not in main loop

它实际上死在下面的 self.canvas.delete(self.id) 上。不运行 PYNPUT/listener 时,如果我单击按钮,一切正常。

def undraw(self):
    if not self.canvas: return
    self.canvas.delete(self.id)
    self.canvas = None
    self.id = None

此时,该游戏中除了用户点击按钮外,没有其他用户输入。我想捕获击键并调用与用户按下按钮时相同的方法。

打开调试器,我看到我得到了我的密钥,然后调用了“播放”函数。它永远不会进入播放功能的第二行。

这是我从 GitHub 获得的一款游戏,并根据我的喜好进行了调整。所以我试图在结构上尽可能少地改变它。

主程序基本上是这样的:

def main():
    # first number is width, second is height
    screenWidth = 800
    screenHeight = 500
    mainWindow = GraphWin("Game", screenWidth, screenHeight)
    game = game(mainWindow)
    listener = keyboard.Listener(on_press=game.on_press)
    listener.start()
    game.go()
    mainWindow.close()

if __name__ == '__main__':
    main()

我在 Game 类中添加了一个测试函数,它目前没有触发。

def on_press(self, key):
    print("on_press: key=" + str(key))
    if key == keyboard.KeyCode(char='p'):
        print("calling self.play()")
        self.play()

def play( self , event=''):
    """ User pressed the Play button. """
    self.message1.setMsg() # 
    self.message2.setMsg() # <--- I never reach here! 

message1 和 2 在游戏构造函数中定义:

    self.message1 = MessageBox(win, Point(xmax*0.55, m1y))
    self.message2 = MessageBox(win, Point(xmax*0.55, m2y))

最后,MessageBox 代码在 textboxes.py 中:

class MessageBox:
    "Just a Text area to display a message in"
    def __init__( self, win, center ):
        self.win = win
        self.center = center
        self.set = False

    def setMsg( self, msg=None ):
        """Show a message, call with no parameters to
        remove the score from the screen"""
        if msg:
            self.msgLine = Text( self.center, msg )
            self.msgLine.setFill("gold")
            #self.msgLine.setSize( 12 )
            #self.msgLine.setStyle( "bold" )
            self.msgLine.draw( self.win )
            self.set = True
        elif self.set:
            self.msgLine.undraw( )
            self.set = False

    def setColor( self, color ):
        "Change the text color"
        self.msgLine.setFill( color )
        #self.msgLine.setSize( 13 )

标签: python-3.xkeyboard-shortcutspynput

解决方案


推荐阅读