15

I am trying to find a way to detect a keypress and then run a method depending on what key it is.

I can already do this with Tkinter. But what I can't do is detect the keypress while the window is in the background. I will be running this program in the background while I play a game. I need it to be able to detect inputs while I'm in the game.

Is there any way I can do this with Tkinter or something else? Preferably I would like to not have to download anything external as I would like to distribute this to some other people.

Slidedrum
  • 151
  • 1
  • 1
  • 4
  • Are you saying you want to detect all keyboard activity like a key logger, or maybe just a single key to get the program in the foreground again? In the latter case, you may have luck with your desktop environment's hotkey configuration. – tdelaney Nov 23 '15 at 05:03
  • `Autokey` is a program to detect keypress and run scripts. It is written in python. Check its source code. Especially IOMediator class - https://code.google.com/p/autokey/source/browse/trunk/src/lib/iomediator.py – furas Nov 23 '15 at 05:07
  • 2
    operation system doesn't send key events to programs in background so you need something like in `pykeylogger` or `pyhook` – furas Nov 23 '15 at 05:17
  • What platform is this on? – poolie Nov 23 '15 at 06:16

4 Answers4

6

pyHook seems like it would work well for this (mentioned by furas)

from pyHook import HookManager
from win32gui import PumpMessages, PostQuitMessage

class Keystroke_Watcher(object):
    def __init__(self):
        self.hm = HookManager()
        self.hm.KeyDown = self.on_keyboard_event
        self.hm.HookKeyboard()


    def on_keyboard_event(self, event):
        try:
            if event.KeyID  == keycode_youre_looking_for:
                self.your_method()
        finally:
            return True

    def your_method(self):
        pass

    def shutdown(self):
        PostQuitMessage(0)
        self.hm.UnhookKeyboard()


watcher = Keystroke_Watcher()
PumpMessages()
user2682863
  • 3,097
  • 1
  • 24
  • 38
6

I suggest not to use pyHook anymore, because it's an old, not maintained library (last updated in 2008) Alternatively there are many other libraries, which are actively maintained for example pynput:

from pynput.keyboard import Key, Listener


def on_press(key):
    print('{0} pressed'.format(key))


def on_release(key):
    print('{0} release'.format(key))
    if key == Key.esc:
        return False


with Listener(on_press=on_press, on_release=on_release) as listener:
    listener.join()

keyboard can be an another alternative which may be worth considering.

Andy
  • 341
  • 5
  • 10
  • I end up in an infinite loop. How can I listen for only the first key pressed? If I press `Esc` my program just enters a weird state where nothing prints. – Daniel Duque Dec 20 '21 at 16:31
3

Too get all the properties from your key press event. you can do the following

import pythoncom, pyHook

def OnKeyboardEvent(event):
    print('MessageName:',event.MessageName)
    print('Message:',event.Message)
    print('Time:',event.Time)
    print('Window:',event.Window)
    print('WindowName:',event.WindowName)
    print('Ascii:', event.Ascii, chr(event.Ascii))
    print('Key:', event.Key)
    print('KeyID:', event.KeyID)
    print('ScanCode:', event.ScanCode)
    print('Extended:', event.Extended)
    print('Injected:', event.Injected)
    print('Alt', event.Alt)
    print('Transition', event.Transition)
    print('---')

# return True to pass the event to other handlers
    return True

# create a hook manager
hm = pyHook.HookManager()
# watch for all mouse events
hm.KeyDown = OnKeyboardEvent
# set the hook
hm.HookKeyboard()
# wait forever
pythoncom.PumpMessages()

Now know all the details of the key press and do operation on top of this.

pressing 's' would look like this

MessageName: key down
Message: 256
Time: 449145375
Window: 2558060
WindowName: "file name"
Ascii: 115 s
Key: S
KeyID: 83
ScanCode: 31
Extended: 0
Injected: 0
Alt 0
Transition 0
1

See pynput.

def on_release(key):
    
    global running
    
    if key == keyboard.Key.esc:
        running = False;

running = True

listener = keyboard.Listener(on_release=on_release)
# run listener in background so that the while loop gets executed
listener.start()

while running
    print("running some code")

listener.stop()
I-CubeX
  • 41
  • 4