I’m writing an application in tkinter which has the following structure:
- Notebook
- Tab (frame on the notebook)
- Canvas (on the frame)
- SecondFrame (on the canvas) ← this is where I want to pack my buttons
- MyButtons (on second frame)
While scrollbar is linked as expected to my canvas.
Lets say I have 20 buttons when running the program and by pressing any of them I want to destroy the last button
This is my code:
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.geometry('300x300')
root.title('Update Scrollbar')
notebook = Notebook(root)
tab1 = Frame(notebook)
notebook.add(tab1, text='Home')
notebook.pack(expand=1, fill='both')
canvas = Canvas(tab1)
second_frame = Frame(canvas)
scrollbar = Scrollbar(tab1, orient='vertical', command=canvas.yview)
canvas.create_window((0, 0), window=second_frame, anchor='center')
scrollbar.pack(side='right', fill='y')
canvas.config(yscrollcommand=scrollbar.set)
canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox('all')))
canvas.pack()
# With this function I destroy the last button:
def delete_buttons():
list(second_frame.winfo_children())[-1].destroy()
second_frame.update_idletasks()
# Here I pack my buttons all with a command 'delete_buttons'
for i in range(20):
Button(second_frame, text='Button' + str(i), command=delete_buttons).pack()
root.mainloop()
However when clicking on a button, the last button is destroyed but an ugly space is created in the top and bottom of the window. (Because of a missing button that took space before I suppose.)
Advertisement
Answer
The space is appearing because of the anchor=
option you’re using to create the Canvas
window object:
canvas.create_window((0, 0), window=second_frame, anchor='center')
Which causes the contents to be re-centered every time one of the Button
s is deleted.
To prevent some of the extra space resulting from the deletion from getting distributed to the top of the Canvas
, simply anchor the window object to its NorthWest (upper left) corner like this:
canvas.create_window((0, 0), window=second_frame, anchor='nw')
Also note that second_frame.update_idletasks()
call in the delete_buttons()
function isn’t necessary.