Zdarzenia w tkinter

WPROWADZENIE

Aplikacje powinny wykonywać działania, kiedy pojawią się pewne zdarzenia, np. naciśnięcie przycisku w aplikacji, naciśnięcie klawisza klawiatury lub myszy, zmiana rozmiaru aplikacji. Użytkownik powinien napisać kod (obsługę zdarzenia), który będzie uruchamiany w odpowiedzi na zdarzenie.

Metoda 'mainloop()' utrzymuje listę zdarzeń otrzymanych od systemu operacyjnego i uruchamia obsługę zdarzenia za każdym razem, kiedy nowe zdarzenie zostaje dodane do listy zdarzeń.

Najczęściej używane zdarzenia to niskopoziomowe zdarzenia systemu operacyjnego, np. kliknięcie myszy "<Button-1>", zmiana rozmiaru lub pozycji widżetu "<Configure>". Wiele widżetów generuje także wysokopoziomowe, semantyczne zdarzenia, zwane 'zdarzeniami wirtualnymi'. Oznaczane są przez podwójne ostre nawiasy ("<<virtual_event>>"). Przykładem może być zaznaczenie przez użytkownika elementu na liście 'Listbox'.

UŻYCIE BIND


# event1.py
import tkinter as tk

root = tk.Tk()

def handle_keypress(event):
    """Print the character associated to the key pressed."""
    print("The key {} was pressed!".format(event.char))

def handle_keyrelease(event):
    """Print the character associated to the key released."""
    print("The key {} was released!".format(event.char)) # no char

def handle_click(event):
    print("Clicked at {} {}".format(event.x, event.y))

# Bind keypress event to handle_keypress().
# The output is printed to stdout.
# Tutaj zdarzenia są dowiązane do głównego okna (root).

#root.bind(event_string, event_handler)
#root.bind("<Key>", handle_keypress)
#root.bind("<Key>", lambda event: print(event.char))
root.bind("<KeyPress>", handle_keypress)   # the same as "<Key>"
root.bind("<KeyRelease>", handle_keyrelease)

root.bind("<Return>", lambda event: print("Return was pressed"))
root.bind("<Escape>", lambda event: print("Escape was pressed"))
root.bind("<BackSpace>", lambda event: print("BackSpace was pressed"))
root.bind("<Tab>", lambda event: print("Tab was pressed"))
# Cursors.
root.bind("<Up>", lambda event: print("Up was pressed"))
root.bind("<Down>", lambda event: print("Down was pressed"))
root.bind("<Left>", lambda event: print("Left was pressed"))
root.bind("<Right>", lambda event: print("Right was pressed"))

# Mouse clics.
root.bind("<Button-1>", handle_click)   # the left mouse button
root.bind("<Button-2>", handle_click)   # the middle mouse button
root.bind("<Button-3>", handle_click)   # the right mouse button
root.bind("<Button-4>", handle_click)   # scroll up
root.bind("<Button-5>", handle_click)   # scroll down
#root.bind("<Button-3>", lambda event: print(event.char))   # prints ??
root.bind("<Double-1>", lambda event: print("left double-click"))
root.bind("<Double-2>", lambda event: print("middle double-click"))
root.bind("<Double-3>", lambda event: print("right double-click"))

root.bind("<Motion>", lambda event: print("a mouse pointer is moved"))
root.bind("<Configure>", lambda event: print("a window is resized|repositioned|..."))
root.bind("<Destroy>", lambda event: print("a window is destroyed"))

root.bind("<Enter>", lambda event: print("mouse enters a window"))
root.bind("<Leave>", lambda event: print("mouse leaves a window"))

root.bind("<Map>", lambda event: print("a window is opened"))
root.bind("<Unmap>", lambda event: print("a window is iconified"))

root.bind("<FocusIn>", lambda event: print("a window gains focus"))
root.bind("<FocusOut>", lambda event: print("a window loses focus"))

root.mainloop()   # run the tkinter event loop

# Modyfikatory.

"<Motion>" and "<B1-Motion>" (moving the mouse with the left button pressed)
"<KeyPress>" and "<KeyPress-a>" (pressing the "a" key only)

# Synonimy.

"<ButtonPress-1>", "<Button-1>", "<1>"
"<Double-ButtonPress-1>", "<Double-1>"
"<KeyPress-a>", "<Key-a>"

# Konfiguracja widżetu w reakcji na zdarzenie.
import tkinter as tk

root = tk.Tk()
label = tk.Label(root, text="Initial string")
label.grid()

# Zdarzenia są dowiązane do widżetu Label.
label.bind('<Enter>', lambda event: label.configure(text='Moved mouse inside'))
label.bind('<Leave>', lambda event: label.configure(text='Moved mouse outside'))

root.mainloop()

UŻYCIE COMMAND

Każdy widżet Button ma atrybut 'command', który służy do podstawienia funkcji. Jeśli przycisk zostanie naciśnięty, wtedy uruchamiana jest funkcja.


# +---+---+---+
# | - | 0 | + |
# +---+---+---+
# event2.py
import tkinter as tk

# Funkcje do zmiany tekstu wyświetlanego przez etykietę.
# Funkcje korzystają ze zmiennej globalnej 'label'.
def increase():
    value = int(label["text"])
    label["text"] = "{}".format(value + 1)

def decrease():
    value = int(label["text"])
    label["text"] = "{}".format(value - 1)

root = tk.Tk()

root.rowconfigure(0, minsize=100, weight=1)
root.columnconfigure(0, minsize=100, weight=1)
root.columnconfigure(1, minsize=100, weight=1)
root.columnconfigure(2, minsize=100, weight=1)

button_decrease = tk.Button(root, text="-", command=decrease)
# command=lambda: label.config(text=str(int(label["text"])-1)))
button_decrease.grid(row=0, column=0, sticky=tk.NSEW)

label = tk.Label(root, text="0")
label.grid(row=0, column=1)

button_increase = tk.Button(root, text="+", command=increase)
# command=lambda: label.config(text=str(int(label["text"])+1)))
button_increase.grid(row=0, column=2, sticky=tk.NSEW)

root.mainloop()   # run the tkinter event loop

# Użycie zmiennej tkinter.
import tkinter as tk

root = tk.Tk()

root.rowconfigure(0, minsize=100, weight=1)
root.columnconfigure(0, minsize=100, weight=1)
root.columnconfigure(1, minsize=100, weight=1)
root.columnconfigure(2, minsize=100, weight=1)

var = tk.StringVar()
var.set(0)   # automatyczna konwersja na string

button_decrease = tk.Button(root, text="-",
    command=lambda: var.set(int(var.get()) - 1))
button_decrease.grid(row=0, column=0, sticky=tk.NSEW)

label = tk.Label(root, textvariable=var)   # zmienna tkinter
label.grid(row=0, column=1)

button_increase = tk.Button(root, text="+",
    command=lambda: var.set(int(var.get()) + 1))
button_increase.grid(row=0, column=2, sticky=tk.NSEW)

root.mainloop()   # run the tkinter event loop