I am new to tkinter. I have a list of buttons A and when I select one of the buttons I can also update a label (see code). Now I would like to have a second list of buttons B where the number of buttons (and functionality) depends on the click on a button from the list of buttons A (I tried to show this in the picture).
What am I doing wrong here? Can you help me please!
import tkinter as tk
root = tk.Tk()
root.title("Analyser")
root.geometry("750x250")
group_number = tk.StringVar()
l0 = tk.Label(root, textvariable=group_number, width=20)
l0.grid(row=1,column=1)
def func(n):
group_number.set("Selected Button: Button " str(n 1))
Buttons_A = ["Button 1","Button 2"]
l2 = tk.Label(root, text = "BUTTONS A",font=('Helvetica', 12, "bold"), fg='white', bg='#107baf', width=20)
l2.grid(row=0, column=0,padx=4,pady=8)
for i in range(len(Buttons_A)):
btn=tk.Button(root, text=Buttons_A[i], font=('Helvetica', 10), bg='#d8e7ea', width=20, activebackground='#42bed8')
btn.config(command=lambda n=i:func(n))
btn.grid(row=i 1,column=0, padx=4,pady=4)
Buttons_B_1 = ["Button 1","Button 2","Button 3"]
Buttons_B_2 = ["Button 1"]
l2 = tk.Label(root, text = "BUTTONS B",font=('Helvetica', 12, "bold"), fg='white', bg='#107baf', width=20)
l2.grid(row=0, column=2,padx=4,pady=8)
for i in range(len(Buttons_B_1)):
btn=tk.Button(root, text=Buttons_B_1[i], font=('Helvetica', 10), bg='#d8e7ea', width=20, activebackground='#42bed8')
btn.config(command=lambda n=i:func(n))
btn.grid(row=i 1,column=2, padx=4,pady=4)
root.mainloop()
When Button 1 is selected from Button List A When Button 2 is selected from Button List A
CodePudding user response:
You should keep buttons B on list so you could easily destroy them.
When you click button A then it runs func
and inside this function you should destroy buttons from list, clear this list, create new buttons and add them to this list.
Code will be simpler if you will keep buttons B1 and B2 as sublists on one list.
Minimal working code.
I removed fonts and colors to show only important elements.
import tkinter as tk
# --- functions ---
def func(n):
group_number.set(f"Selected Button: Button {n 1}")
create_buttons_B(n)
def create_buttons_B(selected_button_1):
# remove previous buttons
for button in existing_buttons_B:
button.destroy()
# clear list
existing_buttons_B.clear()
# create new buttons and add to list
buttons = Buttons_B[selected_button_1]
for number, text in enumerate(buttons):
btn = tk.Button(root, text=text)
btn.grid(row=number 1, column=2)
existing_buttons_B.append(btn)
# --- main ---
Buttons_A = ["Button 1", "Button 2"]
Buttons_B = [
["Button B1 1", "Button B1 2", "Button B1 3"],
["Button B2 1"],
]
existing_buttons_B = [] # list for created buttons B
root = tk.Tk()
group_number = tk.StringVar(root)
l0 = tk.Label(root, textvariable=group_number, width=20)
l0.grid(row=1, column=1)
l2 = tk.Label(root, text="BUTTONS A")
l2.grid(row=0, column=0)
for number, text in enumerate(Buttons_A):
btn = tk.Button(root, text=text, command=lambda n=number:func(n))
btn.grid(row=number 1, column=0)
l2 = tk.Label(root, text="BUTTONS B")
l2.grid(row=0, column=2)
#create_buttons_B(0) # create buttons at start
root.mainloop()
Eventually you could use Frame
to group buttons and then you have to destroy only this Frame
and it will destroy also buttons.
But you can also first create Frames with buttons and put buttons in frames and later use grid_forget()
to remove one frame and grid()
to show another frame.
CodePudding user response:
It is easier to associate the required lists using dictionary for Buttons_A
instead of separated lists:
Buttons_A = {
"Button 1": ["Button 1", "Button 2", "Button 3"],
"Button 2": ["Button 1"]
}
Also better use frames to group buttons, so that you can just destroy buttons in "BUTTONS B" and then create new ones whenever a button in "BUTTONS A" is clicked.
import tkinter as tk
root = tk.Tk()
root.title("Analyser")
root.geometry("750x250")
group_number = tk.StringVar()
l0 = tk.Label(root, textvariable=group_number, width=20)
l0.grid(row=1, column=1, sticky='n')
def func(btn):
group_number.set("Selected Button: " btn)
# clear current buttons shown in frame_B
for w in frame_B.winfo_children():
w.destroy()
# populate required buttons
for item in Buttons_A[btn]:
btn = tk.Button(frame_B, text=item, font=('Helvetica', 10), bg='#d8e7ea', width=20, activebackground='#42bed8')
btn.pack(padx=4, pady=4)
Buttons_A = {
"Button 1": ["Button 1", "Button 2", "Button 3"],
"Button 2": ["Button 1"]
}
l2 = tk.Label(root, text="BUTTONS A", font=('Helvetica', 12, "bold"), fg='white', bg='#107baf', width=20)
l2.grid(row=0, column=0, padx=4, pady=8)
# frame for "Buttons A"
frame_A = tk.Frame(root)
frame_A.grid(row=1, column=0, sticky='n')
for item in Buttons_A:
btn = tk.Button(frame_A, text=item, font=('Helvetica', 10), bg='#d8e7ea', width=20, activebackground='#42bed8')
btn.config(command=lambda x=item:func(x))
btn.pack(padx=4, pady=4)
l2 = tk.Label(root, text="BUTTONS B", font=('Helvetica', 12, "bold"), fg='white', bg='#107baf', width=20)
l2.grid(row=0, column=2, padx=4, pady=8)
# frame for "Buttons B"
frame_B = tk.Frame(root)
frame_B.grid(row=1, column=2, sticky='n')
root.mainloop()