首页 > 解决方案 > tkinter 滚动区域不更新

问题描述

我试图让滚动条在我的 tkinter 应用程序中使用上一篇文章:在 Tkinter 中向一组小部件添加滚动条。如果我在 for 循环之前取消注释代码,一切都可以正常工作,但据我(有限)理解,我相信如果我取消注释 for 循环内的代码,它也应该工作。据我了解,调用canvas.configure(scrollregion=canvas.bbox("all"))应该更新画布的滚动区域以包含放置在框架内的所有标签小部件。第一个只是在每次将新标签小部件添加到框架时自动执行,frame.bind("<Configure>",onFrameConfigure)而第二个手动执行,那么有什么区别?为什么它不起作用?

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()

标签: pythontkinter

解决方案


第一个只是在每次使用 frame.bind("",onFrameConfigure) 将新标签小部件添加到框架时自动执行,而第二个手动执行,那么有什么区别?为什么它不起作用?

bbox不同之处在于,响应事件的调用发生框架实际绘制到屏幕上之后。在循环中调用它意味着在小部件可见并且它们的大小不确定之前调用它。

bbox如果您在循环内调用(update_idletasks或者可能update,取决于平台)强制在屏幕上绘制小部件,则在循环内调用将起作用。但是,在循环完成后立即调用它会更有效,这样在添加所有小部件后才调用一次。


推荐阅读