4

I have been looking around for a long time for answers to this question but still hasn't find anything. I am creating a GUI using Tkinter, and I have two buttons that do mostly the same thing except they receive information from different widgets. One button is for an Entry widget and the other is for a Listbox widget. The callback function for these two buttons is long (about 200 lines), so I don't want to have separate functions for each button. I have if-statements in the beginning of this callback function to check which button is clicked, and then the codes will take the corresponding value. But I am not sure if the following code shows the right way to do this because apparently it doesn't work perfectly in my program. The callback function would only work for the first time, and if I click the other button I will receive an error. Here is a sample code that I created to illustrate the idea. Note that I want to check if the button is clicked, I do not want to check if the 'value' exists. Please help.

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()
mechanical_meat
  • 163,903
  • 24
  • 228
  • 223
ecco
  • 53
  • 1
  • 4
  • This isn't really answering your question, but what you could do instead is make three functions: one which only gets the value when you click button 1, another function which only gets the value when you click button 2, and the third function which contains your 200-line function. Then, the first two functions could just call the third one and pass in the values so you don't need the `if` statement cluttering things up. – Michael0x2a Apr 19 '13 at 22:09

1 Answers1

6

If you want to pass the actual widget into the callback, you can do it like this:

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

Another choice is to simply pass in a literal string if you don't really need a reference to the widget:

button1 = Button(..., command=lambda widget="button1": DoSomething(widget))
button2 = Button(..., command=lambda widget="button2": DoSomething(widget))

Another choice is to give each button a unique callback, and have that callback do only the thing that is unique to that button:

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

There are other ways to solve the same problem, but hopefully this will give you the general idea of how to pass values to a button callback, or how you can avoid needing to do that in the first place.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thank you so much Bryan! I figured my logic was totally wrong and this really helped. – ecco Apr 22 '13 at 17:41