1

I want to make btn using for loop

import tkinter as tk

root = tk.Tk()

win_width  = 355
win_height = 312

root.geometry("{}x{}+{}+{}".format(win_width,win_height,
                                   int(root.winfo_screenwidth()/2  - win_width/2),
                                   int(root.winfo_screenheight()/2 - win_height/2)-50))

beats = ['']*16
instrument = 'kick'

def set_beat(x,num):
    global instrument,beats
    
    beats[num] = '' if beats[num]==instrument else instrument
    x['text'] = beats[num]
    # x==.!button16

btn_list = []
row,col = 0,0
for i in range(16):
    btn = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[i],i))
    btn.grid(row=row,column=col,padx=5,pady=5)
    btn_list.append(btn)
    col+=1
    if col==4: row+=1;col = 0

root.mainloop()

but I click any btn, the list only changes text of the last btn

if I do it btn by btn, it works fine

import tkinter as tk

root = tk.Tk()

win_width  = 355
win_height = 312

root.geometry("{}x{}+{}+{}".format(win_width,win_height,
                                   int(root.winfo_screenwidth()/2  - win_width/2),
                                   int(root.winfo_screenheight()/2 - win_height/2)-50))

beats = ['']*16
instrument = 'kick'

def set_beat(x,num):
    global instrument,beats
    
    beats[num] = '' if beats[num]==instrument else instrument
    x['text'] = beats[num]

_1 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[0],0))
_1.grid(row=0,column=0,padx=5,pady=5)
_2 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[1],1))
_2.grid(row=0,column=1,padx=5,pady=5)
_3 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[2],2))
_3.grid(row=0,column=2,padx=5,pady=5)
_4 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[3],3))
_4.grid(row=0,column=3,padx=5,pady=5)

_5 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[4],4))
_5.grid(row=1,column=0,padx=5,pady=5)
_6 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[5],5))
_6.grid(row=1,column=1,padx=5,pady=5)
_7 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[6],6))
_7.grid(row=1,column=2,padx=5,pady=5)
_8 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[7],7))
_8.grid(row=1,column=3,padx=5,pady=5)

_9 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[8],8))
_9.grid(row=2,column=0,padx=5,pady=5)
_10 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[9],9))
_10.grid(row=2,column=1,padx=5,pady=5)
_11 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[10],10))
_11.grid(row=2,column=2,padx=5,pady=5)
_12 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[11],11))
_12.grid(row=2,column=3,padx=5,pady=5)

_13 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[12],12))
_13.grid(row=3,column=0,padx=5,pady=5)
_14 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[13],13))
_14.grid(row=3,column=1,padx=5,pady=5)
_15 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[14],14))
_15.grid(row=3,column=2,padx=5,pady=5)
_16 = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[15],15))
_16.grid(row=3,column=3,padx=5,pady=5)

btn_list = [_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16]

root.mainloop()

I don't want to use btn by btn, bc that's a lot of codes help me plssssssssssssssssssssssssssssssssssssssssssssssssss


(this is the first time I have asked a question on stack overflow)
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685

1 Answers1

0

as @jasonharper 's link says this problem can be solve really easily
in the for-loop you've to change this line

btn = tk.Button(root,text='     ',command=lambda: set_beat(btn_list[i],i))

to this line:

btn = tk.Button(root,text='     ',command=lambda i=i :set_beat(btn_list[i],i))

the problem is that in this case command=lambda: set_beat(btn_list[i],i) name i is not available

Dmitriy Neledva
  • 867
  • 4
  • 10