Python pynput - ключи захвата - необработанное исключение в обратном вызове слушателя - основной поток не находится в основном цикле - PullRequest
0 голосов
/ 16 июня 2020

У меня тут двойной вопрос, когда я пытался связать с TKinter. Но я готов использовать PYNPUT, если это поможет мне быстрее заставить мои функции работать.

Я изучал этот Pyhon - «Необработанное исключение в обратном вызове слушателя» с помощью pynput , и это помогло некоторым, но я не прошел мимо ошибки.

С помощью 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

В настоящее время в этой игре нет никаких действий пользователя, кроме нажатия кнопок. Я хочу зафиксировать нажатия клавиш и вызвать тот же метод, который был бы вызван, если бы пользователь нажал кнопку.

С включенным отладчиком я вижу, что получаю свой ключ, затем вызываю функцию "play". Он никогда не попадает на вторую строку функции воспроизведения.

Это игра, которую я получил с 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! 

сообщения 1 и 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 )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...