В моем приложении, чтобы избежать необходимости заставлять каждый виджет получать фокус до того, как появится возможность захвата событий KeyPress, я решил использовать root.bind_all(), чтобы позволить корневому окну захватывать все эти события. Я хочу иметь возможность различать, например, «a», «Alt+a», «Shift+a» и «Control+a».
Ниже представлена простая программа, в которой у меня есть 4 разных блока кода, проведенные мной тесты и полученные результаты:
Код: Выделить всё
import tkinter as tk
from tkinter import ttk
class App:
def __init__(self, root):
self.root = root
label = ttk.Label(self.root, text="Key binding test", takefocus=True)
label.pack()
# BLOCK 1: to test this block, uncomment it and comment the rest of blocks
self.root.bind_all("", self.change_color)
# My results:
# Test 1.1: Press 'a' -> 'Event captured: a'
# Test 1.2: Press Shift -> 'Event captured: Shift_L'
# Test 1.3: Press Shift+a -> 'Event captured: Shift_L'
# 'Event captured: A'
# Test 1.4: Press Alt -> no event captured
# Test 1.5: Press Alt+a -> no event captured
# Test 1.6: Press Control -> 'Event captured: Control_L'
# Test 1.7: Press Control+a -> 'Event captured: Control_L'
# 'Event captured: a'
# Test 1.8: Press Alt gr -> 'Event captured: Control_L'
# BLOCK 2: to test this block, uncomment it and comment the rest of blocks
#self.root.event_add("",
# "",
# "",
# ""
# )
#self.root.bind_all("", self.change_color)
# My results:
# Test 2.1: Press Shift -> no event captured
# Test 2.2: Press Shift+a -> no event captured
# Test 2.3: Press Alt -> no event captured
# Test 2.4: Press Alt+a -> 'Event captured: a'
# Test 2.5: Press Control -> no event captured
# Test 2.6: Press Control+a -> 'Event captured: a'
# BLOCK 3: to test this block, uncomment it and comment the rest of blocks
#self.root.event_add("",
# "",
# "",
# ""
# )
#self.root.bind_all("", self.change_color)
# My results:
# Test 3.1: Press Shift -> 'Event captured: Shift_L'
# Test 3.2: Press Alt -> no event captured
# Test 3.3: Press Control -> 'Event captured: Control_L'
# BLOCK 4: to test this block, uncomment it and comment the rest of blocks
#self.root.bind_all("", self.change_color)
#self.root.bind_all("", self.change_color)
#self.root.bind_all("", self.change_color)
# My results:
# Test 4.1: Press Alt -> 'Event captured: Alt_L'
# Test 4.2: Press Shift -> 'Event captured: Shift_L'
# Test 4.3: Press Control -> 'Event captured: Control_L'
def change_color(self, event):
# Ideally do the change color stuff
print('Event captured: ', event.keysym)
# Also tested with
# return "break"
# and
# return ("break")
# and
# return
if __name__ == '__main__':
root = tk.Tk()
app = App(root)
root.mainloop()
Как видно,
Тест 1.2 захватывает Shift_L, а тест 1.4 не захватывает Alt_L.
Тесты 2.1 и 2.2 не фиксируют нажатие Shift
Тесты 2.4 и 2.6 просто печатают «a», что означает, что я не знаю если сначала в качестве модификаторов использовались Alt или Control
Тест 3.2 не фиксировал Alt_L, а Тест 4.1 — это делал! А тест 1.4 этого не сделал!
Я пробовал менять
Код: Выделить всё
"",
"",
""
Код: Выделить всё
"",
"",
""
Привязки «Alt» не работают в текстовом виджете tkinter
но я получил те же результаты.
Есть идеи по поводу этого «странного поведения»? Может ли это зависеть от ОС?
Я использую Python 3.14 в Windows 11.
Я тестировал его на ноутбуке Dell, а также на ноутбуке HP с внешней клавиатурой, подключенной через USB-порт.
Единственный способ заставить его работать — использовать здесь подход Symon:
Привязка кнопок к нажатиям клавиш Alt?
определить предложенные им функции AltOn и AltOff и создать новые ShiftOn, ShiftOff, ControlOn и ControlOff.>
Подробнее здесь: https://stackoverflow.com/questions/798 ... in-tkinter
Мобильная версия