JJP7
JJP7

Reputation: 33

tkinter scrollregion not updating

I was trying to get the scrollbar to work, in my tkinter application with this previous post: Adding a scrollbar to a group of widgets in Tkinter. Everything is working fine if I uncomment out the code before the for loop, but to my (limited) understanding, I believe that it should also work if I uncomment out the code inside of the for loop instead. As I understand it, calling canvas.configure(scrollregion=canvas.bbox("all")) should update the scrollregion of the canvas to include all of the label widgets that are placed inside of the frame. The first one just does it automatically every time a new label widget gets added into the frame with frame.bind("<Configure>",onFrameConfigure) while the second does it manually, so what's the difference? Why doesn't it work?

import tkinter

root = tkinter.Tk()
canvas = tkinter.Canvas(root)
frame = tkinter.Frame(canvas)

scrollbar=tkinter.Scrollbar(root,orient="vertical",command=canvas.yview)
canvas.configure(yscrollcommand=scrollbar.set)

scrollbar.pack(side="right", fill="y")
canvas.pack(fill="both", expand=True)

canvas.create_window((0, 0), window=frame, anchor="nw")

# works 
#def onFrameConfigure(event):
#    canvas.configure(scrollregion=canvas.bbox("all"))
# 
#frame.bind("<Configure>", onFrameConfigure)

for x in range(100):

     new_label = tkinter.Label(frame, text="%d"%x)
     new_label.pack()

     # doesn't work
     #canvas.configure(scrollregion=canvas.bbox("all"))

root.mainloop()

Upvotes: 0

Views: 1438

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385860

The first one just does it automatically every time a new label widget gets added into the frame with frame.bind("",onFrameConfigure) while the second does it manually, so what's the difference? Why doesn't it work?

The difference is that calling bbox in response to an event happens after the frame has actually been drawn on the screen. Calling it within the loop means it is called before the widgets are visible and their size is indeterminate.

Calling bbox inside the loop will work if you call update_idletasks (or maybe update, depending on the platform) inside the loop to force the widgets to be drawn on the screen. Though, it would be far more efficient to call it immediately after the loop has complete so that it is called once after all widgets have been added.

Upvotes: 1

Related Questions