Home > Blockchain >  Pygame not detecting duplicate keyboard input events
Pygame not detecting duplicate keyboard input events

Time:01-14

We're building a hardware device using a raspberry pi with a barcode scanner and a display. The barcode scanner functions like a USB keyboard, and sends keystrokes in quick succession after scanning a barcode. We're having a problem with pygame not detecting duplicate keys from the scanner in quick succession. When running the below code, pygame often misses duplicate keys. Example output from scanning the same barcode:

5770857738
5770857738
570857738
577085738
57085738
5770857738
577085738
5770857738
5770857738
5770857738
5770857738
577085738
5770857738
570857738
5770857738

If I comment out the last three lines however (not updating the screen), the code is scanned successfully every time.

We're using pygame 2.1.2 with python 3.9.2 on a raspberry pi.

import sys, pygame
pygame.init()
screen = pygame.display.set_mode((800, 400))
ID = ""
font = pygame.font.SysFont("Arial", 70)
while True:
    text = font.render("testtext", True, (255, 255, 255), (0, 0, 0))
    textRect = text.get_rect()
    textRect.center = (screen.get_width() // 2, screen.get_height() // 2)
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.KEYDOWN:
            key = pygame.key.name(event.key)
            if key.isdigit():
                ID  = key
            elif key == "return":
                print(ID)
                ID = ""
            elif key == "left":
                pygame.quit()
                sys.exit()
    screen.fill((0, 0, 0))
    screen.blit(text, textRect)
    pygame.display.flip()

From testing it looks like there is about 3-4 miliseconds between each keystroke being sent by the scanner.

We've tried detecting keystrokes in a separate thread with different libraries, but have so far not found a workable solution.

CodePudding user response:

If I comment out the last three lines however (not updating the screen), the code is scanned successfully every time.

I would use an if statement to temporarily "comment out" these lines when input from the barcode scanner is received:

import sys, pygame
pygame.init()
screen = pygame.display.set_mode((800, 400))
ID = ""
font = pygame.font.SysFont("Arial", 70)
scanning = False
while True:
    text = font.render("testtext", True, (255, 255, 255), (0, 0, 0))
    textRect = text.get_rect()
    textRect.center = (screen.get_width() // 2, screen.get_height() // 2)
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.KEYDOWN:
            key = pygame.key.name(event.key)
            if key.isdigit():
                scanning = True
                ID  = key
            elif key == "return":
                scanning = False
                print(ID)
                ID = ""
            elif key == "left":
                pygame.quit()
                sys.exit()
    if not scanning:
        screen.fill((0, 0, 0))
        screen.blit(text, textRect)
        pygame.display.flip()

As I don't have a barcode scanner, I'm unable to test this code. I have tested using keyboard input, but I have no idea of the time delay between my different keystrokes. All my tests were passed correctly

CodePudding user response:

Your main loop is notorious for not adding any delay between screen frame updates - this will make the screen updtae use 100% CPU - and it is likely the event engine is doing the equivalent of "frame skiping" when it finally has a chance to run.

Just add a pygame.time.delay(30) (pause 30 miliseconds) after the call to .display.flip() - that should give your O.S. a breath to catch up with the events. Since you said that commenting out any screen updates, it works, I am confident that given this space you should be fine.

  • Related