2

I am creating a keyboard in TKinter. pressing a button should just print out the text for that button. For some reason every button prints out ctrl which is the last button created. How do I change it so that it actually prints out the respective text for each button?

 def press(key):
     print(key)

 def createWidgets(self):
    for tup in layout.layout:
        for key, value in tup:
            button = Button(self, text=key, command=lambda: self.press(key))
            self.kboard_buttons.append(button)
            button.pack(side="left")
5
  • I can't see anything wrong with the code you posted. Could you paste the entire code into a gist at gist.github.com and post the link here? Commented Nov 11, 2014 at 23:46
  • I can see wrong only in print(key) that is misindented, if such a word exists... Commented Nov 11, 2014 at 23:47
  • Could you please try lambda k=key: self.press(k) and let us know of your findings? Commented Nov 12, 2014 at 0:00
  • Well, iCodez flashed a similar answer while I was writing my comment so I'm now pretty sure my suggestion was correct! Commented Nov 12, 2014 at 0:02
  • 1
    @JayronHubbard The answer by iCodez below is both correct and helpful, really helpful with regard to your misunderstanding, the gist is not really necessary any longer. Go and approve... Ciao from Commented Nov 12, 2014 at 0:05

1 Answer 1

2

The expression inside a lambda function is evaluated when the function is called, not when it is defined. This means that the key in:

command=lambda: self.press(key)

will always refer to the last value held by key in the for-loop.

You can fix this problem by simply capturing the value of key as a default argument for the lambda:

command=lambda key=key: self.press(key)

Because default arguments are evaluated when a function is defined, this will ensure that the key inside the lambda refers to the current value of key inside the for-loop and not the last value.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you! Would you also be able to explain to me why my keyboard looks so out of whack? I'm trying to make it look like a real keyboard. I posted a link to the github in one of my comments.
You need to play around with your arguments to grid in order to space the buttons correctly. For example, removing columnspan=value makes things look a lot better. Other than that, it is just a matter of tweaking the values of the arguments. Here is a reference on the available arguments to configure the behavior of grid: effbot.org/tkinterbook/grid.htm
Additionally, you should never call grid on the same line as you create a widget because grid always returns None. So, kboard_buttons will be a list of None in the end.
But I need some of the keys to be different columnspan such as the enter and space key. The correct column span should be the value i set it to so I'm not sure why that screws things up. So wouldn't I have to call grid when I create the widgets?
What I mean is don't do something like button = Button(...).grid(...) because button will be assigned to None. Instead, do button = Button(...) and then on the next line button.grid(...).

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.