By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,564 Members | 834 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,564 IT Pros & Developers. It's quick & easy.

Getting the sender widget's name in function (Tkinter)

P: n/a
I have the following script. Two widgets call the same function. How
can I tell inside of the called function which button called it?:

def say_hello():
print 'hello!'
print widget['text']

root = Tk()
button1 = Button(root, text='Button 1', command=say_hello)
button1.pack()
button2 = Button(root, text='Button 2', command=say_hello)
button2.pack()
root.mainloop()

Thanks,

Harlin Seritt

Jul 19 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
Harlin Seritt wrote:
I have the following script. Two widgets call the same function. How
can I tell inside of the called function which button called it?:


As far as I know you can't (but I can be proven wrong).
You may try to define a class to solve this (not tested):

####
class say_hello:
def __init__(self, text):
self.text=text
def __call__(self)
print 'Hello!'
print self.text

root = Tk()
button1 = Button(root, text='Button 1', command=say_hello('Button 1'))
button1.pack()
button2 = Button(root, text='Button 2', command=say_hello('Button 2'))
button2.pack()
root.mainloop()
####
Jul 19 '05 #2

P: n/a
from Tkinter import Tk, Button

def say_hello(event):
print 'hello!'
print event.widget['text']

root = Tk()
button1 = Button(root, text='Button 1')
button1.bind('<Button-1>', say_hello)
button1.pack()
button2 = Button(root, text='Button 2')
button2.bind('<Button-1>', say_hello)
button2.pack()
root.mainloop()

Jul 19 '05 #3

P: n/a
On 26 Apr 2005 13:37:29 -0700, infidel <sa***********@gmail.com> wrote:
from Tkinter import Tk, Button

def say_hello(event):
print 'hello!'
print event.widget['text']

root = Tk()
button1 = Button(root, text='Button 1')
button1.bind('<Button-1>', say_hello)
button1.pack()
button2 = Button(root, text='Button 2')
button2.bind('<Button-1>', say_hello)
button2.pack()
root.mainloop()


Unfortunately, making a binding to <Button-1> on Button widgets does not have the same behavior as setting their 'command' option. The binding will fire when the button is *pressed*; the command will be called when the button is *released*. So, binding to <ButtonRelease-1> instead of <Button-1> make things a little better, but still does not have the same effect, since ButtonPress and ButtonRelease events are balanced: the widget getting the ButtonRelease event is always the same as the one getting the ButtonPress event. So if the mouse button is pressed inside the Button, then the mouse pointer goes out of it, and then the mouse button is released, the Button will still get the ButtonRelease event and fire the binding. This is not the normal behavior for a button and this is not the behavior you get via the 'command' option (just try it...).

So having a different function for each button or using tiissa's solution is definitely better.

HTH
--
python -c "print ''.join([chr(154 - ord(c)) for c in 'U(17zX(%,5.zmz5(17;8(%,5.Z65\\'*9--56l7+-'])"
Jul 19 '05 #4

P: n/a
In article <op**************@eb.pragmadev>,
Eric Brunel <er*********@despammed.com> wrote:
On 26 Apr 2005 13:37:29 -0700, infidel <sa***********@gmail.com> wrote:
from Tkinter import Tk, Button

def say_hello(event):
print 'hello!'
print event.widget['text']

root = Tk()
button1 = Button(root, text='Button 1')
button1.bind('<Button-1>', say_hello)
button1.pack()
button2 = Button(root, text='Button 2')
button2.bind('<Button-1>', say_hello)
button2.pack()
root.mainloop()


Unfortunately, making a binding to <Button-1> on Button widgets does not
have the same behavior as setting their 'command' option. The binding
will fire when the button is *pressed*; the command will be called when
the button is *released*. So, binding to <ButtonRelease-1> instead of
<Button-1> make things a little better, but still does not have the same
effect, since ButtonPress and ButtonRelease events are balanced: the
widget getting the ButtonRelease event is always the same as the one
getting the ButtonPress event. So if the mouse button is pressed inside
the Button, then the mouse pointer goes out of it, and then the mouse
button is released, the Button will still get the ButtonRelease event
and fire the binding. This is not the normal behavior for a button and
this is not the behavior you get via the 'command' option (just try
it...).

So having a different function for each button or using tiissa's
solution is definitely better.

Jul 19 '05 #5

P: n/a
Cameron Laird wrote:
In article <op**************@eb.pragmadev>,
Eric Brunel <er*********@despammed.com> wrote:
Unfortunately, making a binding to <Button-1> on Button widgets does not
have the same behavior as setting their 'command' option.


Without unraveling my own confusion about who has said what to whom, does
everyone realize that Tkinter bind()ings inherently can access the widgets
which generate their events?


I don't know about everyone, but I can assume that's definitively the
case of infidel (who precisely based the solution you quoted on this)
and Eric Brunel.

But that may not be the topic at hand. Indeed, the main point is that,
according to Eric, bind() and command don't behave in the exact same way.

And the OP asked about having a reference on the widget using the
command callback (that, contrary to event-binded callbacks, don't get
passed any argument).
So far, the OP is proposed the choice to either use the event/bind
mecanism or use different callbacks for his different buttons (either
with the method I proposed or not).
Jul 19 '05 #6

P: n/a
Here's a slight variation of tiissa's solution that gives the callable
a reference to the actual widget instead of just it's name:

from Tkinter import Tk, Button

class say_hello:
def __init__(self, widget):
self.widget = widget
def __call__(self):
print 'Hello,', self.widget['text']

def run():
root = Tk()
b1 = Button(root, text='Button 1')
b1.configure(command=say_hello(b1))
b1.pack()
b2 = Button(root, text='Button 2')
b2.configure(command=say_hello(b2))
b2.pack()
root.mainloop()

run()

Jul 19 '05 #7

P: n/a
In article <42***********************@news.free.fr>,
tiissa <ti****@free.fr> wrote:
Jul 19 '05 #8

P: n/a
Cameron Laird wrote:
In article <42***********************@news.free.fr>,
tiissa <ti****@free.fr> wrote:
So far, the OP is proposed the choice to either use the event/bind
mecanism or use different callbacks for his different buttons (either
with the method I proposed or not).


Is there general understanding that "use different
callbacks ..." can be implemented as "parametrize the same callback
with a widget-specific value"?


Tough questions thou ask! Again I can't answer about general
understanding. ;)

However, having myself proposed such a solution in this very thread (and
hinted about it in the above sentence), I do hope most people (at least
those interested in this issue) will be aware of this kind of trick
(without any restriction on the actual implementation). :)
Jul 19 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.