0

Hi,

I'm trying to create 6 buttons in a for loop using tkinter, each button's command points at the same function, but passes a variable (the loop counter.. in this case i) now for some reason.. when i run it, and click on each button, the function is supposed to print the variable passed to it from the button, so i'd expect:

click button 1 -> prints 1 to screen
click button 2 -> prints 2 to screen
etc..

However i end up with:
click button 1 - > prints 6 to screen
click button 2 - > prints 6 to screen again..
click button 3 - > 6 yet again.
etc.. etc

the code i'm using follows:

def buttonClick(button_number):
    print button_number

if __name__ == '__main__':
    root = Tk()
    for i in range(1,6):
        Button(root, text="%i"%(i), command=lambda:buttonClick(i)).grid(row=i, column=2)
        
    root.mainloop()

It seems to be displaying the last value of 'i'?

thanks in advance
a1eio

2
Contributors
3
Replies
4
Views
9 Years
Discussion Span
Last Post by a1eio
0

aah, found out why.

the lambda function needs to be passed the value for 'i' rather than just taking it from the for loop,
instead of:

lambda: buttonClick(i)

it should be:

lambda btn=i: buttonClick(btn)

a1eio

0

Instead of lambda you can also use Python's partial function, new in Python25. Here is a simple example ...

# a tiny Tkinter calculator showing the
# use of the new Python25 partial function

import Tkinter as tk
from functools import partial  # needs Python25 or higher

def click(key):
    global memory
    if key == '=':
        # avoid division by integer
        if '/' in entry.get() and '.' not in entry.get():
            entry.insert(tk.END, ".0")
        # guard against the bad guys abusing eval()
        str1 = "-+0123456789."
        if entry.get()[0] not in str1:
            entry.insert(tk.END, "first char not in " + str1)
        # here comes the calculation part
        try:
            result = eval(entry.get())
            entry.insert(tk.END, " = " + str(result))
        except:
            entry.insert(tk.END, "--> Error!")
    elif key == 'C':
        entry.delete(0, tk.END)  # clear entry
    elif key == '->M':
        memory = entry.get()
        # extract the result
        if '=' in memory:
            ix = memory.find('=')
            memory = memory[ix+2:]
        root.title('M=' + memory)
    elif key == 'M->':
        entry.insert(tk.END, memory)
    elif key == 'neg':
        if '=' in entry.get():
            entry.delete(0, tk.END)
        try:
            if entry.get()[0] == '-':
                entry.delete(0)
            else:
                entry.insert(0, '-')
        except IndexError:
            pass
    else:
        # previous calculation has been done, clear entry
        if '=' in entry.get():
            entry.delete(0, tk.END)
        entry.insert(tk.END, key)

root = tk.Tk()
root.title("My Calculator PF")

# this also shows the calculator's button layout
btn_list = [
'7',  '8',  '9',  '*',  'C',
'4',  '5',  '6',  '/',  'M->',
'1',  '2',  '3',  '-',  '->M',
'0',  '.',  '=',  '+',  'neg' ]

# create all buttons with a loop
r = 1
c = 0
for b in btn_list:
    rel = 'ridge'
    cmd = partial(click, b)  # <-------
    tk.Button(root,text=b,width=5,relief=rel,command=cmd).grid(row=r,column=c)
    c += 1
    if c > 4:
        c = 0
        r += 1

# use Entry widget for an editable display
entry = tk.Entry(root, width=33, bg="yellow")
entry.grid(row=0, column=0, columnspan=5)

root.mainloop()
0

ah that looks interesting, i'll have a look.

thanks

p.s that is an incredibly small calculator, great coding tips in it, thanks.

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.