CodingShark
CodingShark

Reputation: 3

Python Tkinter: create multiple buttons using a loop

I am brand new to Tkinter, and cant figure out how to create multiple buttons by organizing them in a list. I was able to get a single button appear, but when I try to create multiple, it doesn't work, creating a blank page instead.

from tkinter import *
from V2cboard import *
import time


#blueLength=len(blueTokens) # This is the num of blue tokens left on board
#redLength=len(redTokens) # This is the num of red tokens left on board

DispTXT=["Play as Red!","Play as Blue!","Let the Computer play!","Two players!"]
button=[None]

root=Tk()
for i in range(4):
    button[i] = Button(root, text=DispTXT[i], command=boardWindow(i))
    button[i].pack()

root.mainloop()

Please understand that I am new to coding and Tkinter in general.

What I expected to happen was for 4 separate buttons to be created in the window, each with the text from the list above displayed. Then when one would be clicked, it would send the number (i) to my function boardWindow to do something else. I cant get the buttons to appear though, so I thought this might be a syntax error or me misunderstanding how the Button function works? I get the error

can't invoke "button" command: application has been destroyed

when I try to create the buttons?

Upvotes: 0

Views: 2554

Answers (1)

Henry
Henry

Reputation: 3944

The reason only one button appears is because button only has one value, None. button[i] means the ith item in the list button. Because button only has one item, when it tries to change another item, you get an error (List assignment out of range). Instead of changing the item at an index, it is easier to just append it to the end of the list.
The reason clicking on the button does not work is caused by two things. The command parameter takes the name of a function, so don't include the (). Because you need the value of i, you have to use something called a lambda. This allows you to use parameters with commands. command = lambda: boardWindow(i) would work, but it will always use the last value of i, which is not what we want, so we use lambda i=i to keep a unique reference to the value for that button.
Here's the working code:

button=[]

root=Tk()
for i in range(4):
    b = Button(root, text=DispTXT[i], command= lambda i = i: boardWindow(i))
    b.pack()
    button.append(b)

root.mainloop()

Upvotes: 1

Related Questions