Home > database >  Labels Added via Button Command Not Expanding Frame
Labels Added via Button Command Not Expanding Frame

Time:12-03

I am trying to dynamically add labels to a frame contained within a canvas, for scrollbar capability. The labels are being added via a function that is called from a button. The function works fine if called on startup, the frame updates as expected and I have scrollbar capabilities. If I call the function from the button command the frame updates with the labels, but only up to the limit of the starting frame/canvas size. The additional area of the frame containing the rest of the labels won't be visible as the scrollbar isn't "activated"

I tried searching but couldn't find this question being asked before. I am new to Python and Tkinter so apologies if I'm missing something obvious.

from tkinter import *
from tkinter import ttk

root = Tk()
root.geometry("550x550")

main_frame = Frame(root)
main_frame.grid(row = 0, column = 0)

button_frame = Frame(root)
button_frame.grid(row = 1, column = 0)

image_canvas_0 = Canvas(main_frame, height = 500, width = 500)
image_canvas_0.grid(row = 0, column = 0)

image_canvas_0_scrollbar = ttk.Scrollbar(main_frame, orient = VERTICAL, command = image_canvas_0.yview)
image_canvas_0_scrollbar.grid(column = 1, row = 0, sticky = (N,S))

image_canvas_0.config(yscrollcommand = image_canvas_0_scrollbar.set)
image_canvas_0.bind('<Configure>', lambda e: image_canvas_0.configure(scrollregion = image_canvas_0.bbox("all")))

second_frame = Frame(image_canvas_0)
image_canvas_0.create_window((0,0), window = second_frame, anchor = 'nw')

def test_function(*args):
    for i in range(100):
        label_text = 'test'   str(i)
        Label(second_frame, text = label_text).grid(row = i, column = 0)

func_button = Button(button_frame, text = 'Click Me', command = test_function)
func_button.grid(row = 0, column =  0)

#test_function()

root.mainloop()

CodePudding user response:

You aren't changing the scrollregion after you've added widgets to the frame. The canvas doesn't know that there's new data that should be scrollable.

Normally this is done by adding a bind to the frame's <Configure> event, since that event fires whenever the frame changes size.

second_frame.bind("<Configure>", lambda e: image_canvas_0.configure(scrollregion = image_canvas_0.bbox("all")))

The reason your code seems to work when calling the function directly at startup is that you have a similar binding on the canvas itself, which automatically fires once the widget is actually shown on the screen. That happens after you call test_function() when mainloop first starts to run. Once the program starts, the canvas <Configure> event doesn't fire a second time.

  • Related