from tkinter import Tk, Canvas, font from PIL import Image, ImageTk import json import subprocess import pyperclip # Загрузка данных with open("rectangles.json", "r") as f: rectangles = json.load(f) # Загрузка изображения pil_image = Image.open("background_image.png") # Создаём интерфейс Tkinter root = Tk() root.title("SFG Special Symbols Keyboard") # Запретить изменение размера окна root.resizable(False, False) # Создаём Canvas и устанавливаем фон canvas = Canvas(root, width=pil_image.width, height=pil_image.height) canvas.pack() tk_image = ImageTk.PhotoImage(pil_image) canvas.create_image(0, 0, anchor="nw", image=tk_image) key_map = { 0: "Esc", 1: "F1", 2: "F2", 3: "F3", 4: "F4", 5: "F5", 6: "F6", 7: "F7", 8: "F8", 9: "F9", 10: "F10", 11: "F11", 12: "F12", 13: "PrtSc", 14: "ScrL", 15: "Pause", 16: "`", 17: "1", 18: "2", 19: "3", 20: "4", 21: "5", 22: "6", 23: "7", 24: "8", 25: "9", 26: "0", 27: "-", 28: "=", 29: "Backspace", 30: "Ins", 31: "Home", 32: "PgUp", 33: "NumL", 34: "/.", 35: "*.", 36: "-.", 37: "Tab", 38: "q", 39: "w", 40: "e", 41: "r", 42: "t", 43: "y", 44: "u", 45: "i", 46: "o", 47: "p", 48: "[", 49: "]", 50: "\\", 51: "Del", 52: "End", 53: "PgDn", 54: "7.", 55: "8.", 56: "9.", 57: "+.", 58: "Caps", 59: "a", 60: "s", 61: "d", 62: "f", 63: "g", 64: "h", 65: "j", 66: "k", 67: "l", 68: ";", 69: "'", 70: "Enter", 71: "4.", 72: "5.", 73: "6.", 74: "ShiftL", 75: "z", 76: "x", 77: "c", 78: "v", 79: "b", 80: "n", 81: "m", 82: ",", 83: ".", 84: "/", 85: "ShiftR", 86: "↑", 87: "1.", 88: "2.", 89: "3.", 90: "Ret.", 91: "CtrlL", 92: "Win", 93: "Alt", 94: "Space", 95: "AltGr", 96: "Fn", 97: "Menu", 98: "CtrlR", 99: "←", 100: "↓", 101: "→", 102: "Ins.", 103: "Del.", } keycode_map = { 9: "Esc", 67: "F1", 68: "F2", 69: "F3", 70: "F4", 71: "F5", 72: "F6", 73: "F7", 74: "F8", 75: "F9", 76: "F10", 95: "F11", 96: "F12", 107: "PrtSc", 78: "ScrL", 127: "Pause", 49: "`", 10: "1", 11: "2", 12: "3", 13: "4", 14: "5", 15: "6", 16: "7", 17: "8", 18: "9", 19: "0", 20: "-", 21: "=", 22: "Backspace", 118: "Ins", 110: "Home", 112: "PgUp", 77: "NumL", 106: "/.", 63: "*.", 82: "-.", 23: "Tab", 24: "q", 25: "w", 26: "e", 27: "r", 28: "t", 29: "y", 30: "u", 31: "i", 32: "o", 33: "p", 34: "[", 35: "]", 51: "\\", 119: "Del", 115: "End", 117: "PgDn", 79: "7.", 80: "8.", 81: "9.", 86: "+.", 66: "Caps", 38: "a", 39: "s", 40: "d", 41: "f", 42: "g", 43: "h", 44: "j", 45: "k", 46: "l", 47: ";", 48: "'", 36: "Enter", 83: "4.", 84: "5.", 85: "6.", 50: "ShiftL", 52: "z", 53: "x", 54: "c", 55: "v", 56: "b", 57: "n", 58: "m", 59: ",", 60: ".", 61: "/", 62: "ShiftR", 111: "↑", 87: "1.", 88: "2.", 89: "3.", 104: "Ret.", 37: "CtrlL", 133: "Win", 64: "Alt", 65: "Space", 108: "AltGr", 105: "CtrlR", 113: "←", 116: "↓", 114: "→", 118: "Ins", 119: "Del", 90: "Ins.", 91: "Del.", 135: "Menu", } # Словарь специальных символов для физики и математики special_symbols = { "q": "∞", # Бесконечность "w": "∑", # Сумма "e": "∫", # Интеграл "r": "√", # Корень "t": "∂", # Частная производная "y": "≈", # Приблизительно равно "u": "≥", # Больше или равно "i": "≤", # Меньше или равно "o": "⊕", # Прямое суммирование "p": "±", # Плюс-минус "[": "→", # Стрелка вправо "]": "←", # Стрелка влево "a": "⊗", # Тензорное произведение "s": "∝", # Пропорционально "d": "≠", # Не равно "f": "∃", # Существует "g": "∀", # Для всех "h": "∈", # Принадлежит "j": "∉", # Не принадлежит "k": "⊂", # Подмножество "l": "⊃", # Надмножество ";": "∩", # Пересечение "'": "∪", # Объединение "z": "∧", # Логическое И "x": "×", "c": "¬", # Логическое НЕ "v": "∴", # Следовательно "b": "∠", # Угол "n": "°", # Градусы "m": "∥", # Параллельность ",": "≅", # Конгруэнтность ".": "∂", # Частная производная (дублируем для удобства) "/": "÷", # Деление } # Словарь для отслеживания подсветки highlighted_rects = {} # Создаём текстовые подписи для клавиш padding = 8 sym_font = font.Font(family="Arial", size=12, weight="bold", slant="roman") spec_font = font.Font(family="Arial", size=18, weight="bold", slant="roman") for i, (x, y, w, h) in enumerate(rectangles): key_label = key_map.get(i, f"Key {i}") special_symbol = special_symbols.get(key_label, "") rect_id = canvas.create_rectangle(x, y, x + w, y + h, outline="black", width=0) spec_id = canvas.create_text( x + padding + (w - 2 * padding) // 2, y + padding + (h - 2 * padding) // 2, text=special_symbol, font=spec_font, fill="white", ) text_id = canvas.create_text( x + padding, # Смещение на 5 пикселей от левого края y + padding, # Смещение на 5 пикселей от верхнего края text=key_label, font=sym_font, fill="#777777", anchor="nw", # Выравнивание текста по верхнему левому углу ) highlighted_rects[key_label] = rect_id # Обработчик нажатия клавиши def on_key_press(event): if event.keysym == "Escape": root.destroy() # Немедленно закрываем программу при нажатии Escape return key = keycode_map.get(event.keycode) if key in highlighted_rects: # Подсветка клавиши canvas.itemconfig(highlighted_rects[key], outline="red", width=4) # Обработчик отпускания клавиши def on_key_release(event): print(event.keycode) key = keycode_map.get(event.keycode) special_symbol = special_symbols.get(key) if key in highlighted_rects: # Убираем подсветку клавиши canvas.itemconfig(highlighted_rects[key], outline="white", width=2) if special_symbol: pyperclip.copy(special_symbol) # Копируем в буфер root.after(100, root.destroy) # Закрываемся через 100 мс subprocess.Popen(["bash", "-c", "sleep 0.12 ; xdotool key Ctrl+v"]) root.bind("", on_key_press) root.bind("", on_key_release) root.mainloop()