DMarlon Studio

Lección 17 · 17 de 20

Eventos y bind · tkinter

Responda al ratón y al teclado en tkinter con bind: clics, doble clic, movimiento, salida del ratón y teclas, con los datos de cada evento.

tkinter · Eventos y bind en DMarlon Studio: el código del ejemplo y la ventana que abre al ejecutarlo

bind(secuencia, función) une un evento de un componente con una función. La secuencia va entre < > con la forma <Modificador-Tipo-Detalle>: <Button-1> es el botón izquierdo, <Double-Button-1> el doble clic, <Motion> el movimiento, <Leave> la salida del ratón, <Key> cualquier tecla y <Control-s>, Ctrl+S.

La función recibe un objeto Event con los detalles: x e y (la posición dentro del componente), num (qué botón del ratón), keysym (el nombre de la tecla, como "Return" o "a") y char (el carácter que escribe, vacío en teclas como las flechas). clicked los usa para escribir el evento y dibujar un punto donde se hizo clic.

<Button> sin número vale para cualquier botón, y num dice cuál. Las teclas se enlazan a root porque solo las recibe el componente que tiene el foco del teclado, y aquí lo tiene la ventana. Si dos enlaces encajan con la misma tecla, gana el más concreto: Ctrl+S va a su función y no a key.

Al empezar, el lienzo enseña tres puntos de clics anteriores y las etiquetas, un evento de ejemplo; con el ratón encima, la segunda etiqueta sigue la posición en directo.

En DMarlon Studio, la pestaña Eventos del inspector lista los eventos de cada componente (clic, doble clic, clic derecho, entrar, salir…): escriba el nombre de un método y el estudio genera el bind con su secuencia.

Código · main.py

import tkinter as tkfrom tkinter import ttkroot = tk.Tk()root.title("Events")root.geometry("520x300")last = tk.StringVar(value="<Button-1>  at x=300, y=70")where = tk.StringVar(value="Mouse at x=300, y=70")pad = tk.Canvas(root, bg="white", height=180, highlightthickness=1, highlightbackground="#bbbbbb")pad.pack(fill="x", padx=12, pady=12)pad.create_text(10, 8, anchor="nw", fill="gray",                text="Click, double-click or move the mouse here; press any key")ttk.Label(root, textvariable=last, font=("Menlo", 14)).pack()ttk.Label(root, textvariable=where).pack(pady=6)def clicked(event):  # every handler receives an Event with the details    last.set(f"<Button-{event.num}>  at x={event.x}, y={event.y}")    pad.create_oval(event.x - 5, event.y - 5, event.x + 5, event.y + 5, fill="#4f8cf7", width=0)def key(event):  # keysym: the key's name; char: the character it types    last.set(f"<Key>  keysym={event.keysym!r}  char={event.char!r}")# bind(sequence, handler): "<Modifier-Type-Detail>".pad.bind("<Button>", clicked)  # any mouse button; num says which onepad.bind("<Double-Button-1>", lambda e: last.set("<Double-Button-1>"))pad.bind("<Motion>", lambda e: where.set(f"Mouse at x={e.x}, y={e.y}"))pad.bind("<Leave>", lambda e: where.set("The mouse left the pad"))root.bind("<Key>", key)  # keys go to the window that has the focusroot.bind("<Control-s>", lambda e: last.set("<Control-s>  (save)"))for x, y in ((90, 120), (190, 60), (300, 70)):  # three earlier clicks    pad.create_oval(x - 5, y - 5, x + 5, y + 5, fill="#4f8cf7", width=0)root.mainloop()

Para recordar

  • bind("<Secuencia>", función) une evento y función.
  • El Event trae x, y, num, keysym y char.
  • Las teclas llegan al componente que tiene el foco.
  • Entre dos enlaces que encajan, gana el más concreto.

Ejercicio

Ponga la tag «dot» a los puntos del lienzo y haga que la tecla Escape los borre todos con pad.delete("dot"), sin borrar el texto.