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):
    ...

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

Другие вопросы по тегам