Toetsdruk in python detecteren?

Ik maak een programma van het type stopwatch in Python en ik zou graag willen weten hoe ik kan detecteren of een toets wordt ingedrukt (zoals pvoor pauze en svoor stop ), en ik zou niet willen dat het zoiets is als raw_input, dat wacht op de invoer van de gebruiker voordat de uitvoering wordt voortgezet.

Iemand die weet hoe je dit in een while-lus kunt doen?

Ik zou dit graag cross-platform willen maken, maar als dat niet mogelijk is, dan is Linux mijn belangrijkste ontwikkelingsdoel.


Antwoord 1, autoriteit 100%

Python heeft een toetsenbord-module met veel functies. Installeer het, misschien met dit commando:

pip3 install keyboard

Gebruik het dan in code zoals:

import keyboard  # using module keyboard
while True:  # making a loop
    try:  # used try so that if user pressed other than the given key error will not be shown
        if keyboard.is_pressed('q'):  # if key 'q' is pressed 
            print('You Pressed A Key!')
            break  # finishing the loop
    except:
        break  # if user pressed a key other than the given key the loop will break

Antwoord 2, autoriteit 74%

Voor degenen die Windows gebruiken en moeite hadden om een werkend antwoord te vinden, dit is het mijne: 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:
        # Stop listener
        return False
# Collect events until released
with Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

De bovenstaande functie drukt de toets af die u indrukt en start een actie als u de ‘esc’-toets loslaat. De toetsenborddocumentatie is hiervoor een meer gevarieerd gebruik.

Markus von Broadywees op een mogelijk probleem, namelijk: voor dit antwoord hoeft u niet aanwezig te zijn het huidige venster om dit script te activeren, zou een oplossing voor vensters zijn:

from win32gui import GetWindowText, GetForegroundWindow
current_window = (GetWindowText(GetForegroundWindow()))
desired_window_name = "Stopwatch" #Whatever the name of your window should be
#Infinite loops are dangerous.
while True: #Don't rely on this line of code too much and make sure to adapt this to your project.
    if current_window == desired_window_name:
        with Listener(
            on_press=on_press,
            on_release=on_release) as listener:
            listener.join()

Antwoord 3, autoriteit 53%

Er kunnen meer dingen worden gedaan met de keyboard-module.
U kunt deze module installeren met behulp van pip install keyboard
Hier zijn enkele van de methoden:


Methode #1:

De functie read_key():

import keyboard
while True:
    if keyboard.read_key() == "p":
        print("You pressed p")
        break

Dit gaat de lus doorbreken als de toets pwordt ingedrukt.


Methode #2:

Functie gebruiken wait:

import keyboard
keyboard.wait("p")
print("You pressed p")

Het zal wachten tot u op pdrukt en de code voortzet zoals deze wordt ingedrukt.


Methode #3:

De functie on_press_key:

import keyboard
keyboard.on_press_key("p", lambda _:print("You pressed p"))

Het heeft een callback-functie nodig. Ik heb _gebruikt omdat de toetsenbordfunctie de toetsenbordgebeurtenis terugstuurt naar die functie.

Eenmaal uitgevoerd, zal het de functie uitvoeren wanneer de toets wordt ingedrukt. Je kunt alle hooks stoppen door deze regel uit te voeren:

keyboard.unhook_all()

Methode #4:

Deze methode is min of meer al beantwoord door user8167727, maar ik ben het niet eens met de code die ze hebben gemaakt. Het gebruikt de functie is_pressedmaar op een andere manier:

import keyboard
while True:
    if keyboard.is_pressed("p"):
        print("You pressed p")
        break

Het verbreekt de lus als pwordt ingedrukt.


Methode #5:

Je kunt keyboard.recordook. Het registreert alle ingedrukte en losgelaten toetsen totdat je op de escape-toets drukt of degene die je hebt gedefinieerd in untilarg en geeft een lijst met keyboard.KeyboardEventelementen.

import keyboard
keyboard.record(until="p")
print("You pressed p")

Opmerkingen:

  • keyboardleest toetsaanslagen van het hele besturingssysteem.
  • keyboardvereist root op linux

Antwoord 4, autoriteit 38%

Zoals OP vermeldt over raw_input – dat betekent dat hij een cli-oplossing wil.
Linux: vloekenis wat je wilt (windows PDCurses). Curses, is een grafische API voor cli-software, je kunt meer bereiken dan alleen belangrijke gebeurtenissen detecteren.

Deze code detecteert toetsen totdat er op een nieuwe regel wordt gedrukt.

import curses
import os
def main(win):
    win.nodelay(True)
    key=""
    win.clear()                
    win.addstr("Detected key:")
    while 1:          
        try:                 
           key = win.getkey()         
           win.clear()                
           win.addstr("Detected key:")
           win.addstr(str(key)) 
           if key == os.linesep:
              break           
        except Exception as e:
           # No input   
           pass         
curses.wrapper(main)

Antwoord 5, autoriteit 18%

Voor Windowszou je msvcrtals volgt kunnen gebruiken:

  import msvcrt
   while True:
       if msvcrt.kbhit():
           key = msvcrt.getch()
           print(key)   # just to show the result

Antwoord 6, autoriteit 13%

Gebruik deze code om te zien welke toets ingedrukt is

from pynput import keyboard
def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))
def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        return False
# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

Antwoord 7, autoriteit 7%

Gebruik PyGame om een venster te hebben en dan kun je de belangrijkste gebeurtenissen krijgen.

Voor de letter p:

import pygame, sys
import pygame.locals
pygame.init()
BLACK = (0,0,0)
WIDTH = 1280
HEIGHT = 1024
windowSurface = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
windowSurface.fill(BLACK)
while True:
    for event in pygame.event.get():
        if event.key == pygame.K_p: # replace the 'p' to whatever key you wanted to be pressed
             pass #Do what you want to here
        if event.type == pygame.locals.QUIT:
             pygame.quit()
             sys.exit()

Antwoord 8, autoriteit 2%

Ik raad je aan PyGame te gebruiken en een gebeurtenishandle toe te voegen.

http://www.pygame.org/docs/ref/event.html


Antwoord 9, autoriteit 2%

Dus ik heb dit ..soort spel gemaakt… op basis van dit bericht (met behulp van de msvcr-bibliotheek en Python 3.7).

Het volgende is de “hoofdfunctie” van het spel, namelijk het detecteren van de ingedrukte toetsen:

# Requiered libraries - - - -
import msvcrt
# - - - - - - - - - - - - - -
def _secret_key(self):
    # Get the key pressed by the user and check if he/she wins.
    bk = chr(10) + "-"*25 + chr(10)
    while True:
        print(bk + "Press any key(s)" + bk)
        #asks the user to type any key(s)
        kp = str(msvcrt.getch()).replace("b'", "").replace("'", "")
        # Store key's value.
        if r'\xe0' in kp:
            kp += str(msvcrt.getch()).replace("b'", "").replace("'", "")
            # Refactor the variable in case of multi press.
        if kp == r'\xe0\x8a':
            # If user pressed the secret key, the game ends.
            # \x8a is CTRL+F12, that's the secret key.
            print(bk + "CONGRATULATIONS YOU PRESSED THE SECRET KEYS!\a" + bk)
            print("Press any key to exit the game")
            msvcrt.getch()
            break
        else:
            print("    You pressed:'", kp + "', that's not the secret key(s)\n")
            if self.select_continue() == "n":
                if self.secondary_options():
                    self._main_menu()
                break

Als u de volledige broncode van het programma wilt, kunt u deze hier bekijken of downloaden:

Het geheime sleutelspel (GitHub)

(let op: de geheime toetsaanslag is: Ctrl+F12)

Ik hoop dat u als voorbeeld en hulp kunt dienen voor degenen die deze informatie komen raadplegen.


Antwoord 10, autoriteit 2%

Je vermeldt niet of dit een GUI-programma is of niet, maar de meeste GUI-pakketten bevatten een manier om toetsenbordinvoer vast te leggen en af te handelen. Met tkinter(in Py3) kun je bijvoorbeeld binden aan een bepaalde gebeurtenis en deze vervolgens in een functie afhandelen. Bijvoorbeeld:

import tkinter as tk
def key_handler(event=None):
    if event and event.keysym in ('s', 'p'):
        'do something'
r = tk.Tk()
t = tk.Text()
t.pack()
r.bind('<Key>', key_handler)
r.mainloop()

Met het bovenstaande, wanneer u typt in de Tekst-widget, wordt de routine key_handleraangeroepen voor elke (of bijna elke) toets die u indrukt.


Antwoord 11, autoriteit 2%

neoDev’s opmerking bij de vraag zelf is misschien gemakkelijk over het hoofd te zien, maar het verwijst naar een oplossing die hier in geen enkel antwoord wordt genoemd.

Het is niet nodig om keyboardte importeren met deze oplossing.

Oplossing gekopieerd van deze andere vraag, alle credits naar @neoDev.

Dit werkte voor mij op macOS Sierra en Python 2.7.10 en 3.6.3

import sys,tty,os,termios
def getkey():
    old_settings = termios.tcgetattr(sys.stdin)
    tty.setcbreak(sys.stdin.fileno())
    try:
        while True:
            b = os.read(sys.stdin.fileno(), 3).decode()
            if len(b) == 3:
                k = ord(b[2])
            else:
                k = ord(b)
            key_mapping = {
                127: 'backspace',
                10: 'return',
                32: 'space',
                9: 'tab',
                27: 'esc',
                65: 'up',
                66: 'down',
                67: 'right',
                68: 'left'
            }
            return key_mapping.get(k, chr(k))
    finally:
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
try:
    while True:
        k = getkey()
        if k == 'esc':
            quit()
        else:
            print(k)
except (KeyboardInterrupt, SystemExit):
    os.system('stty sane')
    print('stopping.')

Antwoord 12

import cv2
key = cv2.waitKey(1)

Dit komt uit het openCV-pakket. De delayarg is het aantal milliseconden dat wordt gewacht op een toetsdruk. In dit geval 1ms. Volgens de documenten, pollKey()kan worden gebruikt zonder te wachten.


Antwoord 13

Het gebruik van het keyboardpakket, vooral op linux, is geen geschikte oplossing omdat dat pakket root-privileges nodig heeft om te draaien. We kunnen dit eenvoudig implementeren met het getkey-pakket. Dit is analoog aan de C-taalfunctie getchar.

Installeer het:

pip install getkey

En gebruik het:

from getkey import getkey
while True: #Breaks when key is pressed
    key = getkey()
    print(key) #Optionally prints out the key.
    break

We kunnen dit toevoegen aan een functie om de ingedrukte toets terug te geven.

def Ginput(str):
    """
    Now, this function is like the native input() function. It can accept a prompt string, print it out, and when one key is pressed, it will return the key to the caller.
    """
    print(str, end='')
    while True:
        key = getkey()
        print(key)
        return key

Gebruik als volgt:

inp = Ginput("\n Press any key to continue: ")
print("You pressed " + inp)

Antwoord 14

U kunt de toetsenbordmodule gebruiken. Open gewoon terminal en typ:

pip-installatietoetsenbord

Dit is de code:

import keyboard
while true:
    try:
        if keyboard.is_pressed('s'):
            print("stop")
        elif keyboard.is_pressed('p'):
            print("pause")
    except:
        pass

Other episodes