Creating button widgets in a loop tkinter

Question:

I have some code below that creates 26 buttons in a tkinter window with each letter of the alphabet in it. I want the code to print the letter in the button when it is pressed. My code prints z no matter what button is pressed. How could I fix this?

import tkinter as tk
import string

def whenPressed(button):
    print(button['text'])

root = tk.Tk()
alphabet = list(string.ascii_lowercase)
for i in alphabet:
    btn = tk.Button(root, text = i, command = lambda: whenPressed(btn))
    btn.grid(row = alphabet.index(i)//13, column = alphabet.index(i)%13, sticky = 'nsew')
Asked By: Manav Desai

||

Answers:

Try this:

from functools import partial
import tkinter as tk
import string

def whenPressed(button, text):
    print(text)

root = tk.Tk()
alphabet = list(string.ascii_lowercase)
for i in alphabet:
    btn = tk.Button(root, text=i)

    command = partial(whenPressed, btn, i)
    btn.config(command=command)

    row = alphabet.index(i) // 13
    column = alphabet.index(i) % 13
    btn.grid(row=row, column=column, sticky="news")

You have to update the button’s command after you create it using <tkinter.Button>.config(command=...). I also used functools.partial. Its documentation is here. Also it’s usually better to also pass in the text instead of having button["text"].

A little bit of updated version to avoid calculations to use with rows and columns:

from functools import partial
import tkinter as tk
import string

def whenPressed(button, text):
    print(text)

root = tk.Tk()
alphabet = list(string.ascii_lowercase)
for i in range(2):
    for j in range(13):
        text = alphabet[13*i+j]
        btn = tk.Button(root, text=text)
        command = partial(whenPressed, btn, text) # Also can use lambda btn=btn,text=text: whenPressed(btn, text)
        btn.config(command=command)
        btn.grid(row=i, column=j, sticky="news")

root.mainloop()
Answered By: TheLizzard
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.