Bartłomiej 'furas' Burek
furas.pl
# prywatne notatki - Python, Linux, Machine Learning, etc.

Przypisanie funkcji z argumentami do Button w Tkinter

Normalnie command= w Button oczekuje "callback" co oznacza nazwę funkcji bez () i bez argumentów - ale czasami jest potrzeba przyspisania funkcji z argumentem i wtedy można do tego użyć lambda.

command=lambda:function(arg1, arg2, arg3)
import tkinter as tk

def function(text):
    print(text)

root = tk.Tk()

button1 = tk.Button(root, text='Yes', command=lambda:function('Yes'))
button1.pack()

button2 = tk.Button(root, text='No', command=lambda:function('No'))
button2.pack()

root.mainloop()

Jeśli musisz podać widget jak argument w tej funkcji to wtedy można to zrobić już po stworzeniu tego widgeta.

button1["command"] = lambda:function(button1)
import tkinter as tk

def function(widget):
    print(widget['text'])

root = tk.Tk()

button1 = tk.Button(root, text='Yes')
button1.pack()
button1["command"] = lambda:function(button1)

button2 = tk.Button(root, text='No')
button2.pack()
button2["command"] = lambda:function(button2)

root.mainloop()

Jeśli bedziesz używał lambda w pętli to wtedy możesz potrzebować

lambda x=text:function(x)

ponieważ normalnie tekst ze zmiennej text nie jest kopiowany ale jest przypisana tylko referencja/odnośnik do tej zmiennej i ostatecznie wszystkie Buttons będą miały referencje do tej sameh zmienneh z tą samą wartośći - ostatnią wartością użytą w pętli for

import tkinter as tk

def function(text):
    print(text)

root = tk.Tk()

buttons = []

for txt in ('Yes', 'No'):
    # problem: all buttons will print "No"
    #b = tk.Button(root, text=txt, command=(lambda:function(txt))) 

    b = tk.Button(root, text=txt, command=(lambda x=txt:function(x)))
    b.pack()
    buttons.append(b)

root.mainloop()

Jeśli użyjesz bind() aby przypisać zdarzenie z funkcją do widgetu to wtedy funkcja automatycznie dostanie event z informacją o widgecie.

import tkinter as tk

def function(event):
    #print(event)
    print(event.widget['text'])

root = tk.Tk()

button1 = tk.Button(root, text='Yes')
button1.pack()
button1.bind('<Button-1>', function)

button2 = tk.Button(root, text='No')
button2.pack()
button2.bind('<Button-1>', function)

root.mainloop()

BTW: Jeśli checksz tę samą funkcję użyć z command= in bind() wtedy należy użyć wartości domyślej - np. None - aby działała w obu przypadkach

def function(event=None):

ale wtedy nie będzie można wykorzystać wartości przesłanej w event bo nie zawsze będzie dostępna

Książki: python-dla-kazdego-podstawy-programowania python-wprowadzenie python-leksykon-kieszonkowy python-receptury python-programuj-szybko-i-wydajnie python-projekty-do-wykorzystania black-hat-python-jezyk-python-dla-hackerow-i-pentesterow efektywny-python-59-sposobow-na-lepszy-kod tdd-w-praktyce-niezawodny-kod-w-jezyku-python aplikacje-internetowe-z-django-najlepsze-receptury