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

Tkinter event handlers and command callbacks

P: 18
Expand|Select|Wrap|Line Numbers
  1. from Tkinter import *
  2. fields = 'Name', 'Job', 'Pay'
  3.  
  4. def fetch(event,entries):
  5.    for entry in entries:
  6.        print 'Input => "%s"' % entry.get()       # get text
  7.        print  event.widget 
  8.  
  9.  
  10. def makeform(root, fields):
  11.    entries = []
  12.    for field in fields:
  13.        row = Frame(root)                           # make a new row
  14.        lab = Label(row, width=5, text=field)       # add label, entry
  15.        ent = Entry(row)
  16.        row.pack(side=TOP, fill=X)                  # pack row on top
  17.        lab.pack(side=LEFT)
  18.        ent.pack(side=RIGHT, expand=YES, fill=X)    # grow horizontal
  19.        entries.append(ent)
  20.    return entries
  21.  
  22. if __name__ == '__main__':
  23.    root = Tk()
  24.    ents = makeform(root, fields)
  25.    root.bind('<Return>', lambda event,entries=ents: fetch(event,entries))       
  26.    Button(root, text='Fetch', command= lambda event:fetch(event,entries)).pack(side=LEFT)  # #how to revise it?
  27.    root.mainloop()
  28.  
in the code ,the bind method is ok, how to revise "command=lambda event:fetch(event,entries)",to make it work too??
Aug 23 '11 #1

✓ answered by luofeiyu

Expand|Select|Wrap|Line Numbers
  1. from Tkinter import *
  2.  
  3. def fetch(x):
  4.            print x, type(x)
  5.  
  6. if __name__ == '__main__':
  7.            root = Tk()
  8.            button=Button(root,text='Fetch')
  9.            button.pack()
  10.            button.focus_set()
  11.            button.grab_set()
  12.            button.bind('<Return>',fetch)       
  13.            root.mainloop() 
add button.grab_set(),it's ok now

Share this Question
Share on Google+
7 Replies


bvdet
Expert Mod 2.5K+
P: 2,851
The button command callback does not receive an argument. If you want the button to respond to an event and the callback receive the event as an argument, bind an event to it, possibly "<ButtonRelease-1>".
Expand|Select|Wrap|Line Numbers
  1. from Tkinter import *
  2. fields = 'Name', 'Job', 'Pay'
  3.  
  4. def fetch(entries, event=None):
  5.    for entry in entries:
  6.        print 'Input => "%s"' % entry.get()       # get text
  7.        if event:
  8.            print  event.widget 
  9.  
  10.  
  11. def makeform(root, fields):
  12.    entries = []
  13.    for field in fields:
  14.        row = Frame(root)                           # make a new row
  15.        lab = Label(row, width=5, text=field)       # add label, entry
  16.        ent = Entry(row)
  17.        row.pack(side=TOP, fill=X)                  # pack row on top
  18.        lab.pack(side=LEFT)
  19.        ent.pack(side=RIGHT, expand=YES, fill=X)    # grow horizontal
  20.        entries.append(ent)
  21.    return entries
  22.  
  23. if __name__ == '__main__':
  24.    root = Tk()
  25.    ents = makeform(root, fields)
  26.    root.bind('<Return>', lambda event, entries=ents: fetch(entries, event))
  27.    Button(root, text='Fetch', command=lambda:fetch(ents)).pack(side=LEFT)  # #how to revise it?
  28.    root.mainloop()
Aug 23 '11 #2

Expert 100+
P: 624
First, your title makes this thread appear to be a "HowTo", i.e. code that explains how to do something, so you may get fewer readers/respondents as a result.
how to revise "command=lambda event:fetch(event,entries)",to make it work too??
What does this mean? If you mean that your want to pass something to a function when a button is pressed, Python provides "partial". Note that Guido does not like lambda, and planned to remove it in Python 3 as there are better ways to do things. Also, in the fetch() function, you print the same event for each entry in entries. It should be indented at the same level as the for() statement so it only prints once.
Expand|Select|Wrap|Line Numbers
  1. from Tkinter import *
  2. from functools import partial
  3.  
  4. def fetch(event, entries):
  5.        for entry in entries:
  6.            print 'Input => "%s"' % entry.get()       # get text
  7.            if event:
  8.                print  event.widget 
  9.  
  10.  
  11. def makeform(root, fields):
  12.        entries = []
  13.        for field in fields:
  14.            row = Frame(root)                           # make a new row
  15.            lab = Label(row, width=5, text=field)       # add label, entry
  16.            ent = Entry(row)
  17.            row.pack(side=TOP, fill=X)                  # pack row on top
  18.            lab.pack(side=LEFT)
  19.            ent.pack(side=RIGHT, expand=YES, fill=X)    # grow horizontal
  20.            entries.append(ent)
  21.        return entries
  22.  
  23. if __name__ == '__main__':
  24.        fields = 'Name', 'Job', 'Pay'
  25.        root = Tk()
  26.        ents = makeform(root, fields)
  27.  
  28.        ## this can be converted to "partial" as well if you want
  29.        root.bind('<Return>', lambda event, entries=ents: fetch(entries, event))
  30.  
  31.        xb =Button(root, text='Fetch')
  32.        xb.pack(side=LEFT)
  33.  
  34.        ## note that both 'root' & 'xb' bind an object to an event
  35.        ## that is sent to the function
  36.        xb.bind("<Button-1>", partial(fetch, entries=ents))
  37.        root.mainloop() 
Aug 23 '11 #3

P: 18
Expand|Select|Wrap|Line Numbers
  1. from Tkinter import *
  2.  
  3. def fetch(x):
  4.        print  x.type,x
  5.  
  6.  
  7. if __name__ == '__main__':
  8.        root = Tk()
  9.        root.bind('<Return>', fetch)
  10.        root.mainloop()
  11.  
i can get output :
2 <Tkinter.Event instance at 0xb742986c>

Expand|Select|Wrap|Line Numbers
  1. from Tkinter import *
  2.  
  3. def fetch(x):
  4.        print  x.type,x
  5.  
  6.  
  7. if __name__ == '__main__':
  8.        root = Tk()
  9.        button=Button(root,text='Fetch')
  10.        button.pack()
  11.        button.bind('<Return>',fetch)       
  12.        root.mainloop()
  13.  
why i can get nothing when i click enter??
Aug 24 '11 #4

Expert 100+
P: 624
To capture a "Return", you have to set the focus. Otherwise, the focus is not set on the widget so the Return goes to the root window or whatever has focus, and you don't have any bindings for it.
Expand|Select|Wrap|Line Numbers
  1. rom Tkinter import *
  2.  
  3. def fetch(x):
  4.        print x, type(x)
  5.  
  6. if __name__ == '__main__':
  7.        root = Tk()
  8.        button=Button(root,text='Fetch')
  9.        button.pack()
  10.        button.focus_set()
  11.        button.bind('<Return>',fetch)       
  12.        root.mainloop() 
Aug 24 '11 #5

P: 18
you lose f in rom (it is from),i made a try,it'ok,but there is still a problem,
when i finish my first enter,it's ok,there is output ,
when i have a try for the second time ,there is no output??
Aug 24 '11 #6

bvdet
Expert Mod 2.5K+
P: 2,851
Are you losing focus after the first event? You can reset the focus in the callback with x.widget.focus_set()
Aug 24 '11 #7

P: 18
Expand|Select|Wrap|Line Numbers
  1. from Tkinter import *
  2.  
  3. def fetch(x):
  4.            print x, type(x)
  5.  
  6. if __name__ == '__main__':
  7.            root = Tk()
  8.            button=Button(root,text='Fetch')
  9.            button.pack()
  10.            button.focus_set()
  11.            button.grab_set()
  12.            button.bind('<Return>',fetch)       
  13.            root.mainloop() 
add button.grab_set(),it's ok now
Aug 25 '11 #8

Post your reply

Sign in to post your reply or Sign up for a free account.