3

I'm writing a program that displays a grid of buttons, when a button is pressed I want it to print the location of the button in the grid ("row column") out to the console. Here is what I have

import Tkinter as tk

class board(tk.Tk):
    def __init__(self, parent=None):
        tk.Tk.__init__(self,parent)
        self.rows = 5
        self.columns = 5
        self.init_board()

    def init_board(self):
        for i in range(self.rows):
            for j in range(self.columns):
                cmd = lambda: self.button_callback(i,j)
                b = tk.Button(self, text=str("  "), command=cmd)
                b.grid(row=i, column=j)

    def button_callback(self, row, col):
        print(str(row) + " " + str(col))


if __name__ == '__main__':
    board().mainloop()

the problem is that when I click on any of the buttons I get "4 4" printed out which is the location of the last button instantiated in the loop. I don't know why this is happening, please help!

2 Answers 2

7

In the function created using lambda, i, j refers to the varaible in the init_board function, which are set to 4, 4 after the for loop ends.

You can workaround this using default argument.


Replace the following line:

cmd = lambda: self.button_callback(i,j)

with:

cmd = lambda i=i, j=j: self.button_callback(i,j)
Sign up to request clarification or add additional context in comments.

Comments

0

As an addition to what @falsetru has said, You can also use functools.partial.

from functools import partial
# ...
cmd = partial(self.button_callback, i, j)
# ...

Or you can "emulate" partial's behavior like this: (use this snippet instead of the import statement)

def partial(fn, i, j):
    def nested():
        fn(i, j)
    return nested

A better "emulation" can be found here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.