2

I want to get which button was clicked within for loop but i can't able to get button inside the function and the button is generated by for loop and code is this:

from tkinter import * 
from tkinter import ttk

class Application(Tk):
    
    def __init__(self):
        super(Application, self).__init__()
        self.create_grid()

    def create_grid(self):
        for i in range(1, 4):
            self.btn= ttk.Button(self, text="", command=lambda btn=self.btn: self.clik(btn))
            self.btn.grid(ipadx=20, ipady=20, row=i, column=0)


    def clik(self, btn):
        print(btn)


if __name__ == '__main__':
    app = Application()
    app.mainloop()

Error:

    self.btn= ttk.Button(self, text="", command=lambda btn=self.btn: self.clik(btn))
  File "fakepath\__init__.py", line 2346, in __getattr__
    return getattr(self.tk, attr)
AttributeError: '_tkinter.tkapp' object has no attribute 'btn'

Thanks For Any Help.

4
  • 1
    command in separate line self.btn.configure(command=lambda btn=self.btn: self.clik(btn)) Commented Jun 10, 2021 at 7:36
  • You could also from functools import partial and then self.btn.config(command=partial(self.click, self.btn)) (obviously place the import at the beginning of the code) Commented Jun 10, 2021 at 7:41
  • @Matiiss Hey! it also works grate but what is going inside? Commented Jun 10, 2021 at 7:45
  • As far as I understand it just returns a function with the given arguments so that it will run with those arguments every time, basically the same as with the lambda function just shorter and probably has other uses Commented Jun 10, 2021 at 7:54

1 Answer 1

2

In python, the RHS of an assignment is first evaluated and then it stores the value in LHS or so. Here if you notice:

self.btn= ttk.Button(self, text="", command=lambda btn=self.btn: self.clik(btn))

self.btn is only defined after the RHS of this line is evaluated, but inside this line itself you are referencing to the self.btn, which is not defined(yet). Hence the error of not having an attribute btn. So what you can do is assign the command in the next line:

self.btn = ttk.Button(self, text="")
self.btn['command'] = lambda btn=self.btn: self.clik(btn)
Sign up to request clarification or add additional context in comments.

3 Comments

can you join disuccsion?
@TangerCity I do not have the link, you should tag me in it.

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.