You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
7.6 KiB
342 lines
7.6 KiB
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("<KeyPress>", on_key_press) |
|
root.bind("<KeyRelease>", on_key_release) |
|
|
|
root.mainloop()
|
|
|