tkinter generate buttons with names and pass names as an argument when clicked

Question:

I have a code that generates 12 buttons with names from a list. I’d like to pass those names to a function but currently only last text from button is remembered and it’s being used for all buttons.
Is there a way (except creating all buttons manually), to have it worked, meaning that proper button name will be passed further?

import tkinter as tk
from tkinter import *

notes_list = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#']
c = 0
r = 0

def notes(note):

    major_scale_steps = [2,2,1,2,2,2,1]
    minor_scale_notes = [2,1,2,2,1,2,2]

    #find where provided note is located and rearrange notes_list accordingly
    ind = notes_list.index(note)
    n_tran = notes_list[ind:]+notes_list[:ind]

    #gather notes using major_scale_steps
    major_scale = [n_tran[0],n_tran[2],n_tran[4],n_tran[5],n_tran[7],n_tran[9], n_tran[11], n_tran[0]]
    minor_scale = [n_tran[0],n_tran[2],n_tran[3],n_tran[5],n_tran[7],n_tran[8], n_tran[10], n_tran[0]]

    return major_scale

def clicked():
    te = notes(i.config('text')[-1])
    #place label with results
    test = tk.Label(window, text=te)
    test.place(x=100, y=150)
    

window = tk.Tk()
window.title('Guitar notes')
window.geometry('320x250')

#create buttons
for i in notes_list:
    i = Button(window, text=i, command=clicked)
    i.config(height=2, width=10)
    i.grid(column=c, row=r)
    c+=1
    if c == 4:
        c=0
        r+=1


window.mainloop()
Asked By: przystal

||

Answers:

It is because you used i inside clicked(). When clicked() is executed, i will be the last button created in the main for loop.

You should instead pass the required note to clicked() using functools.partial() and use this note to update the test label.

Also better create the test label outside clicked() and update its text inside the function.

import tkinter as tk
from functools import partial

notes_list = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#']

def notes(note):
    #major_scale_steps = [2,2,1,2,2,2,1]
    #minor_scale_notes = [2,1,2,2,1,2,2]

    #find where provided note is located and rearrange notes_list accordingly
    ind = notes_list.index(note)
    n_tran = notes_list[ind:]+notes_list[:ind]

    #gather notes using major_scale_steps
    major_scale = [n_tran[0],n_tran[2],n_tran[4],n_tran[5],n_tran[7],n_tran[9], n_tran[11], n_tran[0]]
    # shorter version of above:
    #major_scale = [n_tran[x] for x in (0, 2, 4, 5, 7, 9, 11, 0)]
    #minor_scale = [n_tran[0],n_tran[2],n_tran[3],n_tran[5],n_tran[7],n_tran[8], n_tran[10], n_tran[0]]

    return major_scale

def clicked(note):
    # update test label
    test.config(text=notes(note))

window = tk.Tk()
window.title('Guitar notes')
window.geometry('320x250')

# create test label here
test = tk.Label(window)
test.place(x=100, y=150)

#create buttons
for i, note in enumerate(notes_list):
    btn = tk.Button(window, text=note, width=10, height=2, command=partial(clicked, note))
    btn.grid(column=i%4, row=i//4)

window.mainloop()
Answered By: acw1668
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.