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.