Python Tkinter одна функция обратного вызова для двух кнопок
Я долго искал ответы на этот вопрос, но до сих пор ничего не нашел. Я создаю графический интерфейс с использованием Tkinter, и у меня есть две кнопки, которые выполняют в основном одно и то же, за исключением того, что они получают информацию из разных виджетов. Одна кнопка предназначена для виджета Entry, а другая - для виджета Listbox. Функция обратного вызова для этих двух кнопок длинная (около 200 строк), поэтому я не хочу иметь отдельные функции для каждой кнопки. У меня есть операторы if в начале этой функции обратного вызова, чтобы проверить, какая кнопка нажата, а затем коды примут соответствующее значение. Но я не уверен, что следующий код показывает правильный способ сделать это, потому что, очевидно, он не работает идеально в моей программе. Функция обратного вызова будет работать только в первый раз, и если я нажму на другую кнопку, я получу сообщение об ошибке. Вот пример кода, который я создал, чтобы проиллюстрировать идею. Обратите внимание, что я хочу проверить, нажата ли кнопка, я не хочу проверять, существует ли "значение". Пожалуйста помоги.
from Tkinter import *
root = Tk()
def DoSomething():
# is this the right way to check which button is clicked?
if button1:
value = user_input.get()
elif button2:
value = choice.get(choice.curselection()[0])
# then more codes that take 'value' as input.
button1 = Button(master,text='Search',command=DoSomething)
button1.pack()
button2 = Button(master,text='Search',command=DoSomething)
button2.pack()
user_input = Entry(master)
user_input.pack()
choice = Listbox(master,selectmode=SINGLE)
choice.pack()
#assume there are items in the listbox, I skipped this portion
root.mainloop()
1 ответ
Если вы хотите передать фактический виджет в обратный вызов, вы можете сделать это следующим образом:
button1 = Button(master, text='Search')
button1.configure(command=lambda widget=button1: DoSomething(widget))
button2 = Button(master, text='Search')
button2.configure(command=lambda widget=button2: DoSomething(widget))
Другой вариант - просто передать литеральную строку, если вам не нужна ссылка на виджет:
button1 = Button(..., command=lambda widget="button1": DoSomething(widget))
button2 = Button(..., command=lambda widget="button2": DoSomething(widget))
Другой вариант - дать каждой кнопке уникальный обратный вызов, и этот обратный вызов должен делать только то, что уникально для этой кнопки:
button1 = Button(..., command=ButtonOneCallback)
button2 = Button(..., command=ButtonTwoCallback)
def ButtonOneCallback():
value = user_input.get()
DoSomething(value)
def ButtonTwoCallback():
value=choice.get(choice.curselection()[0])
DoSomething(value)
def DoSomething(value):
...
Существуют и другие способы решения той же проблемы, но, надеюсь, это даст вам общее представление о том, как передавать значения в функцию обратного вызова кнопки или как избежать необходимости делать это в первую очередь.