Skip to content
Advertisement

How to update a frame with a scrollbar linked in it that has buttons so that it updates and works correctly when adding buttons?

I’m writing an application in tkinter which has the following structure:

  1. Notebook
  2. Tab (frame on the notebook)
  3. Canvas (on the frame)
  4. SecondFrame (on the canvas) ← this is where I want to pack my buttons
  5. 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.)

before pressing any button after pressing any button

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 Buttons 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.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement