Typing Tool
import pygame
import pyttsx3
import keyboard # To block system-level keys
import threading
import queue # For managing speech tasks
# Initialize text-to-speech engine
engine = pyttsx3.init()
# Queue for speech tasks
speech_queue = queue.Queue()
# Function to set the female voice and adjust settings
def set_female_voice():
voices = engine.getProperty('voices')
female_voice = None
for voice in voices:
if 'female' in voice.name.lower():
female_voice = voice
break
if female_voice:
engine.setProperty('voice', female_voice.id)
else:
print("No female voice found. Using default voice.")
engine.setProperty('rate', 200) # Speaking speed
engine.setProperty('volume', 1.0) # Set volume to max
set_female_voice()
# Background thread to process speech from the queue
def speech_worker():
while True:
key = speech_queue.get() # Get the next key from the queue
if key is None: # Sentinel to stop the thread
break
engine.say(key)
engine.runAndWait()
speech_queue.task_done()
# Start the speech worker thread
speech_thread = threading.Thread(target=speech_worker, daemon=True)
speech_thread.start()
# Function to enqueue speech tasks
def speak_key_async(key):
speech_queue.put(key)
# Initialize Pygame
pygame.init()
# Set up the screen for full-screen mode
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
pygame.display.set_caption("Kid's Alphabet and Numbers Typing")
# Set the font and size for larger text
font_size = 420
font = pygame.font.Font(None, font_size)
# Text wrapping settings
margin = 50
line_height = font_size * 1.2
# Allowed keys (a-z, A-Z, 0-9)
allowed_keys_lower = [chr(i) for i in range(97, 123)]
allowed_keys_upper = [chr(i) for i in range(65, 91)]
allowed_keys_numbers = [str(i) for i in range(10)]
# Block system-level keys
keyboard.block_key('windows')
keyboard.block_key('alt')
keyboard.block_key('tab')
# Initialize text content and scroll variables
text = ""
caps_lock = False
scroll_y = 0
max_scroll = 0
def wrap_text(text, font, max_width):
lines = []
current_line = ""
for char in text:
test_line = current_line + char
text_surface = font.render(test_line, True, (0, 0, 0))
if text_surface.get_width() > max_width - 2 * margin:
if current_line:
lines.append(current_line)
current_line = char
else:
current_line = test_line
if current_line:
lines.append(current_line)
return lines
def update_max_scroll_and_scroll(num_lines, screen_height):
global max_scroll, scroll_y
total_text_height = num_lines * line_height
max_scroll = max(0, total_text_height - screen_height)
scroll_y = max_scroll
# Main loop
running = True
while running:
screen.fill((255, 255, 255))
updated = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
key_name = pygame.key.name(event.key)
if event.key == pygame.K_CAPSLOCK:
caps_lock = not caps_lock
if key_name in allowed_keys_lower or key_name in allowed_keys_upper:
if caps_lock or pygame.key.get_mods() & pygame.KMOD_SHIFT:
text += key_name.upper()
speak_key_async(key_name.upper())
else:
text += key_name.lower()
speak_key_async(key_name.lower())
updated = True
elif key_name in allowed_keys_numbers:
text += key_name
speak_key_async(key_name)
updated = True
elif event.key == pygame.K_BACKSPACE:
text = text[:-1]
updated = True
elif event.key == pygame.K_F12:
running = False
if updated:
screen.fill((255, 255, 255))
lines = wrap_text(text, font, screen.get_width())
update_max_scroll_and_scroll(len(lines), screen.get_height())
visible_lines = lines[int(scroll_y // line_height):]
if len(visible_lines) * line_height > screen.get_height():
scroll_y += line_height
for i, line in enumerate(visible_lines):
text_surface = font.render(line, True, (0, 0, 0))
screen.blit(text_surface, (margin, margin + i * line_height - (scroll_y % line_height)))
pygame.display.flip()
# Stop the speech thread gracefully
speech_queue.put(None)
speech_thread.join()
keyboard.unblock_key('windows')
keyboard.unblock_key('alt')
keyboard.unblock_key('tab')
pygame.quit()
Leave a Comment