Reputation: 1263
I have a Tkinter frame that is comprised of two sub-frames, the latter of which has a grid layout. When the user presses a button, the layout of this second frame will change. I've tried to create an example below. The first frame consists of a label containing a random integer between 3 and 8. The second will display between 3 and 8 checkbuttons arranged in three rows. The value between 3 and 8 is chosen at random. When the user presses a button, I want the contents of this second frame to update.
import numpy as np
from tkinter import Tk, Frame,Label, Button, Entry,Label,
TOP,BooleanVar,Checkbutton
from functools import partial
window = Tk()
window.title("My Window")
window.configure(bg='lightgrey')
main_frame=Frame(window,bg='lightgray')
main_frame.pack(side=TOP,expand=True)
random_number_frame=Frame(main_frame)
random_number_frame.pack(side=TOP,expand=True)
random_number_label=Label(random_number_frame,
bg='lightgray',text='Random Integer: ')
random_number_label.pack(side=TOP)
random_number_entry= Label(random_number_frame, width=8)
random_number_entry.pack(side=TOP)
channel_frame=Frame(main_frame,bg='lightgray')
channel_frame.pack(side=TOP,expand=True,pady=10)
channels=['a','b','c','d','e','f','g','h']
def _create_random(channel_frame,random_number_entry):
random_number=np.random.randint(3,8)
random_number_entry.configure(text=str(random_number))
channel_frame.destroy()
channel_frame=Frame(main_frame,bg='lightgray')
channel_frame.pack(side=TOP,expand=True,pady=10)
num_rows=3
channel_vars=[]
channel_buttons=[]
for i in range(np.random.randint(3,8)):
channel_vars.append(BooleanVar())
channel_vars[i].set(False)
channel_buttons.append(Checkbutton(channel_frame,
text=channels[i],var=channel_vars[i],bg='lightgray'))
row_number=3+int(divmod(i,num_rows)[1])
column_number=1+int(divmod(i,num_rows)[0])
channel_buttons[i].grid(sticky="W",row=row_number,
column=column_number)
create_button = Button(main_frame, text="Do It!",
bg='lightgray',command=partial(_create_random,
channel_frame,random_number_entry))
create_button.pack(side=TOP,padx=10)
def _quit():
window.quit()
window.destroy()
quit_button = Button(master=window, text="Quit",
bg='lightgray',command=_quit)
quit_button.pack(side=TOP,padx=10)
window.mainloop()
When I run this and select the "Do It" button, I get what I want. However, if I press the same button again, I see the a new main_frame appended to the old one. I simply want to update the contents of the frames.
I'm sure there is a way to do this and, just as important, to accomplish what I've done this in a far in a more efficient manner.
Upvotes: 0
Views: 461
Reputation: 3275
remove the parameters from the _create_random
and make channel_frame
global also don't forget to change command=partial(_create_random, channel_frame,random_number_entry)
to just command=_create_random
Here is the corrected code:
import numpy as np
from tkinter import Tk, Frame,Label, Button, Entry,Label, TOP,BooleanVar,Checkbutton
from functools import partial
window = Tk()
window.title("My Window")
window.configure(bg='lightgrey')
main_frame=Frame(window,bg='lightgray')
main_frame.pack(side=TOP,expand=True)
random_number_frame=Frame(main_frame)
random_number_frame.pack(side=TOP,expand=True)
random_number_label=Label(random_number_frame,
bg='lightgray',text='Random Integer: ')
random_number_label.pack(side=TOP)
random_number_entry= Label(random_number_frame, width=8)
random_number_entry.pack(side=TOP)
channel_frame=Frame(main_frame,bg='lightgray')
channel_frame.pack(side=TOP,expand=True,pady=10)
channels=['a','b','c','d','e','f','g','h']
def _create_random():
global channel_frame
random_number=np.random.randint(3,8)
random_number_entry.configure(text=str(random_number))
channel_frame.destroy()
channel_frame=Frame(main_frame,bg='lightgray')
channel_frame.pack(side=TOP,expand=True,pady=10)
print(channel_frame)
num_rows=3
channel_vars=[]
channel_buttons=[]
for i in range(np.random.randint(3,8)):
channel_vars.append(BooleanVar())
channel_vars[i].set(False)
channel_buttons.append(Checkbutton(channel_frame, text=channels[i],var=channel_vars[i],bg='lightgray'))
row_number=3+int(divmod(i,num_rows)[1])
column_number=1+int(divmod(i,num_rows)[0])
channel_buttons[i].grid(sticky="W",row=row_number, column=column_number)
create_button = Button(main_frame, text="Do It!",
bg='lightgray',command=_create_random)
create_button.pack(side=TOP,padx=10)
def _quit():
window.quit()
window.destroy()
quit_button = Button(master=window, text="Quit",
bg='lightgray',command=_quit)
quit_button.pack(side=TOP,padx=10)
window.mainloop()
Upvotes: 1