我想在更改其内容后查询小部件的大小。这是一个演示:
import tkinter as tk
win = tk.Tk()
label = tk.Label(win)
label.pack()
def callback1():
label['text'] = 'hello world'
win.after_idle(callback2)
def callback2():
print('label width:', label.winfo_width())
win.after(0, callback1)
win.mainloop()
根据文档after_idle
,只有在无事可做时才应执行排队的回调:
注册一个在系统空闲时调用的回调。回调将被调用,主循环中不再有要处理的事件。
然而,callback2
显然是在调整标签大小之前执行的,因为程序的输出是这样的:
label width: 1
即使添加调用update_idletasks()
也不会更改此输出。仅当在和中都win.update_idletasks()
调用时,才会打印正确的尺寸。我真的不明白为什么有必要调用它两次。 callback1
callback2
问题
为什么callback2
在调整标签大小之前执行?如何确保label.winfo_width()
返回正确的尺寸?
限制
这个问题的主要目标是了解 tkinter 如何/何时执行(空闲)任务。我想了解如何正确地对任务进行排队,以便仅在 GUI 自行更新后才执行它们。我对诸如以下的解决方法并不感兴趣:
- 我宁愿避免使用
update()
,因为我不明白它如何导致竞争条件或何时可以安全使用。(在我的真实代码中,所有这些都将在事件处理程序中执行,文档明确指出应该避免这种情况。) - 我也想避免使用
<Configure>
event。这是因为可能有任意数量的小部件在改变大小,并且不能合理地期望我将事件处理程序绑定到它们的所有<Configure>
事件。在所有调整大小发生后,我真的只需要一种方法来执行回调函数。