Как я могу передать кнопку/метку TKinter, которая вызвала привязку к функции, которую вызывает эта привязка?

#python #tkinter

Вопрос:

Я надеюсь, что кто-нибудь сможет помочь с этим. Я новичок в программировании и хотел попробовать сделать некоторые графические элементы на Python с помощью TKinter. В одном из моих проектов я хочу, чтобы любая кнопка, на которую наведена мышь, меняла цвет фона. Однако я не хочу определять функцию для каждой отдельной кнопки. Вот пример:

 from tkinter import *

root = Tk()
root.title("Example")
root.configure(bg="black")

def on_enter(e, button):
    #button = Button that triggered the bind
    button.configure(bg="red")

def on_leave(e, button):
    #button = Button that triggered the bind
    button.configure(bg="black")

button1 = Button(root, text="Button1", width=10, height=10, bg="black", fg="white")
button2 = Button(root, text="Button2", width=10, height=10, bg="black", fg="white")
button3 = Button(root, text="Button3", width=10, height=10, bg="black", fg="white")
button4 = Button(root, text="Button4", width=10, height=10, bg="black", fg="white")

button1.grid(column=0, row=0)
button2.grid(column=0, row=1)
button3.grid(column=1, row=0)
button4.grid(column=1, row=1)

#How can I give the button that triggered the bind as an argument to the functions on_enter/on_leave?
root.bind_all("<Enter>", lambda e, button: on_enter(e, button))
root.bind_all("<Leave>", lambda e, button: on_leave(e, button))

#root.bind_class("Button", "<Enter>", lambda e, button: on_enter(e, button))
#root.bind_class("Button", "<Leave>", lambda e, button: on_leave(e, button))


root.mainloop()
 

Теперь, конечно, я мог бы пойти и создать функцию для каждой кнопки, чтобы изменить цвет фона, когда привязка для этой конкретной кнопки вызывает эту функцию. Но есть ли способ передать кнопку, которая вызвала привязку, функции, которую вызывает привязка ?

Мой пример работает, если я явно помещу кнопку, которую хочу изменить, в привязку, как это:

 root.bind_all("<Enter>", lambda e, button = button1: on_enter(e, button))
root.bind_all("<Leave>", lambda e, button = button1: on_leave(e, button))
 

Но я подумал, что должен быть более элегантный способ исправить это, кроме создания привязки/функции для каждой отдельной кнопки, которая становится действительно раздражающей, когда у меня есть программа с более чем 4 кнопками.

Надеюсь, у кого-нибудь есть какой-нибудь совет 🙂

Комментарии:

1. Разве это button не аргумент в вашей лямбде? Зачем вам нужно определять функцию для каждой кнопки?

2. @Barмар Да, аргумент там есть, но он пустой. Если я не укажу вручную, какую кнопку она должна передавать в качестве аргумента. Да, для этого потребуется только одна функция, но, в свою очередь, привязка для каждой кнопки. Я в основном просто хочу, чтобы кнопка, которая вызвала bind_all, была передана функции, которую вызывает bind_all (например, on_enter). Таким образом, мне нужно определить только одну функцию и одну привязку.

Ответ №1:

Когда вы связываете событие с функцией, эта функция будет вызвана с объектом, представляющим событие. Этот объект имеет атрибут widget , который является виджетом, получившим событие. Вам не нужно делать ничего другого, чтобы получить виджет.

 def on_enter(event):
    event.widget.configure(bg="red")

root.bind_all("<Enter>", on_enter)