HOWTO · Tkinter

Come passare gli argomenti al comando del pulsante Tkinter

Come passare gli argomenti al comando del pulsante Tkinter

In questa pagina

L’opzione command di un pulsante Tkinter si aspetta un oggetto chiamabile. Per passargli degli argomenti, associane i valori in anticipo e lascia che Tkinter chiami quell’oggetto dopo un clic. Scrivendo command=show_message("Saved"), la funzione viene chiamata mentre il pulsante viene creato; usa partial o un wrapper lambda per rimandare la chiamata.

Passare argomenti con functools.partial

Usa functools.partial quando vuoi associare argomenti a una funzione esistente. Restituisce un oggetto chiamabile con quei valori già associati, quindi può essere assegnato direttamente all’opzione command di un pulsante. Questa simulazione senza interfaccia grafica riproduce l’opzione command di un pulsante, così puoi osservare il comportamento del callback senza aprire una finestra. Esegui questo esempio:

from functools import partial

def show_message(message):
    print(message)

class Button:
    def __init__(self, command):
        self.command = command

    def click(self):
        self.command()

save_button = Button(command=partial(show_message, "Saved"))
remove_button = Button(command=partial(show_message, "Removed"))
save_button.click()
remove_button.click()
Saved
Removed

Ogni clic simulato richiama l’oggetto chiamabile associato e stampa il messaggio. Per aprire una finestra reale, esegui questo script Tkinter completo e fai clic su uno dei due pulsanti: l’etichetta mostra il messaggio e la categoria corrispondenti. Il testo visibile dei pulsanti e dell’etichetta rimane in inglese, perché i blocchi di codice e di output vengono mantenuti invariati:

from functools import partial


def show_message(message, category):
    result.config(text=f"{message} ({category})")


try:
    import tkinter as tk
except ImportError as error:
    print(f"Tkinter is unavailable: {error}")
else:
    try:
        root = tk.Tk()
    except tk.TclError as error:
        print(f"A graphical display is required to open the Tkinter window: {error}")
    else:
        root.title("Button callbacks with partial")
        result = tk.Label(root, text="Choose an action")
        result.pack(padx=12, pady=8)

        tk.Button(
            root,
            text="Save profile",
            command=partial(show_message, "Saved", "profile"),
        ).pack(padx=12, pady=4)
        tk.Button(
            root,
            text="Remove draft",
            command=partial(show_message, "Removed", "draft"),
        ).pack(padx=12, pady=4)

        root.mainloop()

Il callback accetta sia message sia category, in linea con i due valori associati da ciascuna chiamata a partial. partial è utile quando la funzione di destinazione ha già la firma desiderata e vuoi associare uno o più valori direttamente nell’assegnazione a command.

Passare argomenti con una funzione lambda

Una lambda può racchiudere una chiamata e fornire i relativi argomenti quando Tkinter la richiama. L’espressione lambda: show_message("Saved") crea un oggetto chiamabile senza argomenti; la chiamata alla funzione contenuta nel corpo avviene in seguito, al clic. Per una lambda con parametri, la sintassi è lambda parameters: expression.

Questa simulazione senza interfaccia grafica memorizza ogni lambda in uno slot command simile a quello di un pulsante e la richiama per simulare un clic. Esegui questo esempio:

def greet(name):
    print(f"Hello, {name}!")

class Button:
    def __init__(self, command):
        self.command = command

    def click(self):
        self.command()

ada_button = Button(command=lambda: greet("Ada"))
sam_button = Button(command=lambda: greet("Sam"))
ada_button.click()
sam_button.click()
Hello, Ada!
Hello, Sam!

Ogni clic simulato richiama la lambda associata e stampa il saluto selezionato. Per aprire una finestra reale, esegui questo script Tkinter completo e fai clic su uno dei due pulsanti: l’etichetta cambia mostrando il saluto selezionato:

def greet(name):
    result.config(text=f"Hello, {name}!")


try:
    import tkinter as tk
except ImportError as error:
    print(f"Tkinter is unavailable: {error}")
else:
    try:
        root = tk.Tk()
    except tk.TclError as error:
        print(f"A graphical display is required to open the Tkinter window: {error}")
    else:
        root.title("Button callbacks with lambda")
        result = tk.Label(root, text="Choose a greeting")
        result.pack(padx=12, pady=8)

        tk.Button(
            root,
            text="Greet Ada",
            command=lambda: greet("Ada"),
        ).pack(padx=12, pady=4)
        tk.Button(
            root,
            text="Greet Sam",
            command=lambda: greet("Sam"),
        ).pack(padx=12, pady=4)

        root.mainloop()

Scegli partial quando vuoi associare valori a una funzione esistente e rendere visibile l’associazione nell’assegnazione a command. Scegli una lambda se la chiamata richiede una piccola modifica inline o se vuoi rendere esplicita l’espressione del callback accanto al pulsante. Anche una lambda può passare più argomenti, per esempio con lambda: show_message("Saved", "profile"); assicurati che la funzione di destinazione li accetti. In entrambi i casi, assegna a command l’oggetto chiamabile stesso. Aggiungere le parentesi al callback durante la creazione del pulsante lo esegue subito, prima che l’utente possa fare clic. Se il pulsante sembra non fare nulla, controlla che il nome del callback sia corretto, che gli argomenti corrispondano alla firma della funzione e che il corpo della funzione svolga un’azione osservabile, come stampare un messaggio o aggiornare un widget.