
Captura de toques de teclado
Atalhos de Teclado
Na seção Widgets: Atalhos de Teclado vimos como capturar a interação do usuário com o aplicativo através de eventos de teclados. A captura de eventos produzidos pelo teclado se dá através do evento page.on_keyboard_event, que gerencia o pressionamento de teclas de letras em combinação com teclas de controle. Esse evento passa o parâmetro e que é uma instância da classe KeyboardEvent, e tem as seguintes propriedades:
e.key |
Representação textual da tecla pressionada. |
e.shift |
Booleano: True se a tecla “Shift” foi pressionada. |
e.ctrl |
Booleano: True se a tecla “Control” foi pressionada. |
e.alt |
Booleano: True se a tecla “Alt” foi pressionada. |
e.meta |
Booleano: True se a tecla “Meta” foi pressionada††. |
Desta forma conseguimos capturar o pressionamento de uma única letra, além de Enter, Backspace, F1 … F12, Escape, Insert, Page Down, Pause, etc, ou de combinações como Ctrl-F ou Ctrl-Shift-Enter.

Como exemplo adicional vamos exibir o código de um jogo que captura a interação com o teclado. Uma combinação de teclas como Ctrl-H ou SHIFT-L é exibida em um container que desce do topo da página. Se o usuário digita a mesma combinação ele pontua (10 pontos de cada vez) e nova combinação é exibida.
1 import flet as ft
2 import time, random, string
3
4 cores = ["#FFC6C6", "#A8DCEA", "#BAF3E4", "#F1E9AF",
5 "#CBB1CE", "#B2C9F3", "#F0DCBE", "#F1D7B3"]
6
7 def main(page: ft.Page):
8 def sortear():
9 ct.top = 10
10 ct.left = random.randrange(100, 1000)
11 ct.height=80
12 t1 = ["Shift", "Alt", "Ctrl"][random.randrange(0, 3)]
13 t2 = random.choice(string.ascii_letters).upper()
14 ct.content = ft.Text(f"{t1}-{t2}", size=20)
15 ct.bgcolor = cores[random.randrange(0, 8)]
16 ct.visible = True
17
18 def fim(e):
19 page.window_destroy()
20
21 def inicio(e):
22 while True:
23 sortear()
24 while ct.top < 400:
25 time.sleep(.3)
26 ct.top += 10
27 page.update()
28 inicio(e)
29
30 def teclou(e):
31 txt = "Shift" if e.shift else "Alt" if e.alt else "Ctrl" if e.ctrl else ""
32 txt = f"{txt}-{e.key}"
33
34 if ct.content.value == txt:
35 pts = int(txtPontos.value.split(":")[1]) + 10
36 txtPontos.value = f"Sua pontuação: {str(pts)}"
37 ct.bgcolor = "red"
38 while ct.top < 400:
39 time.sleep(.01)
40 ct.top += 10
41 ct.height -= 3
42 page.update()
43
44 ct = ft.Container(padding = 15, width=180, alignment = ft.alignment.center,
45 border = ft.border.all(2, "black"),
46 border_radius = ft.border_radius.all(15),
47 blur=90, visible = False)
48
49 btInicio = ft.ElevatedButton("Começar Jogo", bgcolor="white",
50 width=180, height= 40, on_click=inicio)
51 btFim = ft.ElevatedButton("Terminar Jogo", bgcolor="white",
52 width=180, height= 40, on_click=fim)
53 txtPontos = ft.Text("Sua pontuação: 0", size=27, weight=ft.FontWeight.BOLD)
54 lin = ft.Text("Acerte a combinação de teclas mostrada na tela (Ctrl, Shift, Alt) + Letra",
55 size=27)
56 linha1 = ft.Row([lin], alignment=ft.MainAxisAlignment.SPACE_EVENLY)
57 linha2 = ft.Row([btInicio, txtPontos, btFim],
58 alignment=ft.MainAxisAlignment.SPACE_EVENLY)
59
60 page.add(linha1, linha2, ft.Stack([ct]))
61 page.on_keyboard_event = teclou
62
63 ft.app(target=main)

O início do jogo ocorre quando se clica o botão btInicio que dispara a função inicio(). Dentro dela um loop infinito promove várias interações do container descendo a tela (o que é obtido com container.top += 10). Quando o container chega em seu valor máximo estabelecido, no caso ct.top < 400, novos valores são sorteados como suas propriedades e o container e redesenhado no topo.
O sorteio define a posição (top) inicial, uma cor aleatória escolhida dentro de uma lista de cores (linha 15) e monta uma string para representar uma combinação de teclado (linhas 12 a 14). A linha 13 usa random.choice() para escolher aleatoriamente um dos caracteres de string.ascii_letters, e torná-lo maísculo. Esse carater é juntando à um controle. A tecla de controle Meta (Windows) não foi usada pois é comum que ela esteja associada a atalhos globais do computador, em algumas instalações.

A interação do usuário é capturada em teclou que compara a combinação sorteada com aquela teclada pelo usuário. Se ocorreu um acerto ela incrementa a pontuação, derruba o container (acelerando sua queda) e sorteia nova combinação. O loop infinito iniciado na linha 22 só é terminado com o evento btFim.on_click.
Captura de teclas no Python
Claro que podemos capturar o pressionamento de tecla no Python, sem usar os métodos do Flet. Para isso podemos instalar, entre outras escolhas, o módulo keyboard, que funciona em sistemas operacionais Windows e Linux.
# Instale o módulo de teclado usando PIP: pip install keyboard # No Python 3 instale usando o comando: pip3 install keyboard
Para detectar pressionamentos de teclas podemos usar a função is_pressed(). Esse método recebe um caractere como entrada e retorna True se essa tecla foi pressionada. O exemplo seguinte usa um loop que só é terminado com o pressionamento da tecla f.
import keyboard
print("Pressione 'f' para terminar.")
while True:
if keyboard.is_pressed("a"):
print("A tecla 'f' foi pressionada!")
break
A função keyboard.is_pressed("f") retorna False se qualquer outra tecla fopr pressionada.

Também podemos usar a função read_key() para capturar pressionamentos de teclas. Essa função retorna a tecla pressionada pelo usuário.
import keyboard
while True:
print(keyboard.read_key())
if keyboard.read_key() == "f":
print("Você terminou o loop pressionando 'f'.")
break
Esse código exibe na tela todas as teclas pressionadas até que se tecle “f”.
Outra forma de captura de pressionamento de teclas usa a função wait(), que recebe um caractere como entrada. Quando executado o programa é pausado até que seja pressionada a tecla passada como argumento para a função.
import keyboard
keyboard.wait("f")
print("Você digitou 'f'.")
Nesse último exemplo fica dispensado o uso de um loop para suspender a execução do código.
Bibiografia
- Python for Beginners: How to Detect Keypress in Python
- Alura: Convenções de nomenclatura: Camel, Pascal, Kebab e Snake case.
